In this project, we want to explore the difference between the president that is raised and born in the South(state with slavery) and North, Since after the civil war the cultural boundary between the North and South have been diminished. I just choose presidents from George Washington to Benjamin Harrison, the last president who has became adult before civil war,based on the assumptions that peoples ideology and characteristic are formed in their early adulthood so they should not be influenced by post-war situitions

packages.used=c("rvest", "tibble", "qdap", 
                "sentimentr", "gplots", "dplyr",
                "tm", "syuzhet", "factoextra", 
                "beeswarm", "scales", "RColorBrewer",
                "RANN", "tm", "topicmodels")
# check packages that need to be installed.
packages.needed=setdiff(packages.used, 
                        intersect(installed.packages()[,1], 
                                  packages.used))
# install additional packages
if(length(packages.needed)>0){
  install.packages(packages.needed, dependencies = TRUE)
}
# load packages
library("rvest")
library("tibble")
library("qdap")
library("sentimentr")
library("gplots")
library("dplyr")
library("tm")
library("png")
library("syuzhet")
library("factoextra")
library("beeswarm")
library("scales")
library("RColorBrewer")
library("RANN")
library("tm")
library("topicmodels")
library("xlsx")
library("wordcloud")
library("tidytext")
source("../lib/plotstacked.R")
source("../lib/speechFuncs.R")

This notebook was prepared with the following environmental settings.

print(R.version)
               _                           
platform       x86_64-apple-darwin15.6.0   
arch           x86_64                      
os             darwin15.6.0                
system         x86_64, darwin15.6.0        
status                                     
major          3                           
minor          4.3                         
year           2017                        
month          11                          
day            30                          
svn rev        73796                       
language       R                           
version.string R version 3.4.3 (2017-11-30)
nickname       Kite-Eating Tree            

Data Harvest

we selected all inaugural addresses of past presidents, for lack of data of nominal and farewell addresses of president before civil war.

### Inauguaral speeches
main.page <- read_html(x = "http://www.presidency.ucsb.edu/inaugurals.php")
# Get link URLs
# f.speechlinks is a function for extracting links from the list of speeches. 
inaug=f.speechlinks(main.page)
#head(inaug)
#as.Date(inaug[,1], format="%B %e, %Y")
inaug=inaug[-nrow(inaug),] # remove the last line, irrelevant due to error.

Using speech metadata posted on http://www.presidency.ucsb.edu/, We prepared xlsx data sets for the speeches we will scrap.

picture <- readPNG("map.png")
grid::grid.raster(picture)
#plot(picture)

This is the data I have processed. I just choose presidents from George Washington to Benjamin Harrison, the last president who has became adult before civil war, based on the assumptions that peoples ideology and characteristic are formed in their early adulthood so they should not be influenced by post-war new ideology and impacts.

About one-third presidents were born and raised in the South, while the others were raised in the North part of America. We use the common Mason–Dixon line to seperate south and north as most people do. In the South, most Presidents are from Virginia and Tennessee, in the North there are Presidents from New England, New York , iIlinois etc

inaug.list = read.xlsx("../data/inauglist_place.xlsx", sheetIndex = 1)

We assemble all scrapped speeches into one list. Note here that we dont have the full text yet, only the links to full text transcripts. scrap the texts of speeches from the speech URLs.

inaug.list$type=c(rep("inaug", nrow(inaug.list)))
inaug.list=cbind(inaug.list,inaug)

Based on the list of speeches, we scrap the main text part of the transcript’s html page. For simple html pages of this kind. For reproducibility, we also save our scrapped speeches into our local folder as individual speech files.

Now we combine the information from the internet and dataset, combine the columns of important data frame to generate further useful information, first combine the html and data and then download scripts to local repository.

# Loop over each row in speech.list
inaug.list$fulltext=NA
for(i in seq(nrow(inaug.list))) {
  text <- read_html(inaug.list$urls[i]) %>% # load the page
    html_nodes(".displaytext") %>% # isloate the text
    html_text() # get the text
inaug.list$fulltext[i]=text
  # Create the file name
 #filename <- paste0("../data/inaugurals/", 
#if(inaug.list$File[i]%in% nouu)#levels(sentencep.list.place$File))
#{
  filename <- paste0("../data/inaugurals/", 
                     inaug.list$type[i],
                     inaug.list$File[i], "-", 
                     inaug.list$Term[i], ".txt")
  sink(file = filename) %>% # open file to write 
    cat(text)  # write the file
  sink() # close the file
#}
}

We will use sentences as units of analysis for this project, as sentences are natural languge units for organizing thoughts and ideas. For each extracted sentence, we apply sentiment analysis using NRC sentiment. “The NRC Emotion Lexicon is a list of English words and their associations with eight basic emotions (anger, fear, anticipation, trust, surprise, sadness, joy, and disgust) and two sentiments (negative and positive). The annotations were manually done by crowdsourcing.”

We assign an sequential id to each sentence in a speech (sent.id) and also calculated the number of words in each sentence as sentence length (word.count).

sentence.list=NULL
for(i in 1:nrow(inaug.list)){
  sentences=sent_detect(inaug.list$fulltext[i],
                        endmarks = c("?", ".", "!", "|",";"))
  if(length(sentences)>0){
    emotions=get_nrc_sentiment(sentences)
    word.count=word_count(sentences)
    # colnames(emotions)=paste0("emo.", colnames(emotions))
    # in case the word counts are zeros?
    emotions=diag(1/(word.count+0.01))%*%as.matrix(emotions)
    sentence.list=rbind(sentence.list, 
                        cbind(inaug.list[i,-ncol(inaug.list)],
                              sentences=as.character(sentences), 
                              word.count,
                              emotions,
                              sent.id=1:length(sentences)
                        )
    )
  }
}

Some non-sentences exist in raw data due to erroneous extra end-of-sentence marks. And we also delete presidents that do not belong to our Category.

sentence.list=sentence.list%>%filter(!is.na(word.count)) 
sentence.list.place<-sentence.list[as.logical(1-is.na(sentence.list$Places)),]

Data analysis — length of sentences

For simpler visualization, we chose a subset of better known presidents or presidential candidates on which to focus our analysis. Let us haveOverview of sentence length distribution by different types of speeches. let us see how presidents inaugural length from different regions differ

inaugural speeches

par(mar=c(4, 11, 2, 2))
sentence.list.place$File=factor(sentence.list.place$File)
sentence.list.place$FileOrdered=reorder(sentence.list.place$File, 
                                      sentence.list.place$word.count, 
                                      mean, 
                                      order=T)
# this is for each president
sentence.list.place$Filedirection=paste(sentence.list.place$FileOrdered,sentence.list.place$Places)
beeswarm(word.count~Filedirection, 
         data=sentence.list.place,
         horizontal = TRUE, 
         pch=16, 
         col=alpha(brewer.pal(9, "Set1"), 0.6), 
         cex=0.55, cex.axis=0.8, cex.lab=0.8,
         spacing=5/nlevels(sentence.list.place$FileOrdered),
         las=2, xlab="Number of words in a sentence.", ylab="",
         main="Inaugural speeches")

# this is for overall places
beeswarm(word.count~Places,
         data=sentence.list.place,
         horizontal = TRUE, 
         pch=16, 
         col=alpha(brewer.pal(9, "Set1"), 0.6), 
         cex=0.55, cex.axis=0.8, cex.lab=0.8,
         spacing=5/nlevels(sentence.list.place$FileOrdered),
         las=2, xlab="Number of words in a sentence.", ylab="",
         main="Inaugural speeches")

And we want explore the short sentences presidents usually say:

#president from South
sentence.list.place%>%
  filter(File=="GeorgeWashington",word.count<=10)%>%
  select(sentences)#%>%sample_n(10)
sentence.list.place%>%
  filter(File=="JohnAdams", 
         word.count<=10)%>%
  select(sentences)
sentence.list.place%>%
  filter(File=="AbrahamLincoln", 
         word.count<=10)%>%
  select(sentences)#%>%sample_n(10)
#
folder.path="../data/inaugurals/"
ff.all<-Corpus(DirSource(folder.path))
ff.all<-tm_map(ff.all, stripWhitespace)
ff.all<-tm_map(ff.all, content_transformer(tolower))
ff.all<-tm_map(ff.all, removeWords, stopwords("english"))
ff.all<-tm_map(ff.all, removeWords, character(0))
ff.all<-tm_map(ff.all, removePunctuation)
tdm.all<-TermDocumentMatrix(ff.all)
tdm.tidy=tidy(tdm.all)
tdm.overall=summarise(group_by(tdm.tidy, term), sum(count))
wordcloud(tdm.overall$term, tdm.overall$`sum(count)`,
          scale=c(5,0.5),
          max.words=100,
          min.freq=1,
          random.order=FALSE,
          rot.per=0.3,
          use.r.layout=T,
          random.color=FALSE,
          #colors="BLUE"))
          colors=brewer.pal(9,"Blues"))

# the 
folder.path1="../data/inaugurals/beforewar/"
ff.beforewar<-Corpus(DirSource(folder.path1))
ff.beforewar<-tm_map(ff.beforewar, stripWhitespace)
ff.beforewar<-tm_map(ff.beforewar, content_transformer(tolower))
ff.beforewar<-tm_map(ff.beforewar, removeWords, stopwords("english"))
ff.beforewar<-tm_map(ff.beforewar, removeWords, character(0))
ff.beforewar<-tm_map(ff.beforewar, removePunctuation)
tdm.allbef<-TermDocumentMatrix(ff.beforewar)
tdm.tidybef=tidy(tdm.allbef)
tdm.overallb=summarise(group_by(tdm.tidybef, term), sum(count))
wordcloud(tdm.overallb$term, tdm.overallb$`sum(count)`,
          scale=c(5,0.5),
          max.words=100,
          min.freq=1,
          random.order=FALSE,
          rot.per=0.3,
          use.r.layout=T,
          random.color=FALSE,
          #colors="BLUE"))
          colors=brewer.pal(9,"Greens"))

folder.pathn="../data/inaugurals/beforewar/north"
ff.alln<-Corpus(DirSource(folder.pathn))
ff.alln<-tm_map(ff.alln, stripWhitespace)
ff.alln<-tm_map(ff.alln, content_transformer(tolower))
ff.alln<-tm_map(ff.alln, removeWords, stopwords("english"))
ff.alln<-tm_map(ff.alln, removeWords, character(0))
ff.alln<-tm_map(ff.alln, removePunctuation)
tdm.alln<-TermDocumentMatrix(ff.alln)
tdm.tidyn=tidy(tdm.alln)
tdm.overalln=summarise(group_by(tdm.tidyn, term), sum(count))
wordcloud(tdm.overalln$term,tdm.overalln$`sum(count)`,
          scale=c(5,0.5),
          max.words=100,
          min.freq=1,
          random.order=FALSE,
          rot.per=0.3,
          use.r.layout=T,
          random.color=FALSE,
          #colors="BLUE"))
          colors=brewer.pal(9,"Reds"))

folder.paths="../data/inaugurals/beforewar/south"
ff.alls<-Corpus(DirSource(folder.paths))
ff.alls<-tm_map(ff.alls, stripWhitespace)
ff.alls<-tm_map(ff.alls, content_transformer(tolower))
ff.alls<-tm_map(ff.alls, removeWords, stopwords("english"))
ff.alls<-tm_map(ff.alls, removeWords, character(0))
ff.alls<-tm_map(ff.alls, removePunctuation)
tdm.alls<-TermDocumentMatrix(ff.alls)
tdm.tidys=tidy(tdm.alls)
tdm.overalls=summarise(group_by(tdm.tidys, term), sum(count))
wordcloud(tdm.overalls$term, tdm.overalls$`sum(count)`,
          scale=c(5,0.5),
          max.words=100,
          min.freq=1,
          random.order=FALSE,
          rot.per=0.3,
          use.r.layout=T,
          random.color=FALSE,
          #colors="BLUE"))
          colors=brewer.pal(9,"Blues"))

Data analysis

Sentence length variation over the course of the speech, with emotions.

How our presidents (or candidates) alternate between long and short sentences and how they shift between different sentiments in their speeches. It is interesting to note that some presidential candidates’ speech are more colorful than others.

par(mfrow=c(4,1), mar=c(1,0,2,0), bty="n", xaxt="n", yaxt="n", font.main=1)
f.plotsent.len(In.list=sentence.list, InFile="GeorgeWashington", 
InType="inaug", InTerm=1, President="George Washington")
f.plotsent.len(In.list=sentence.list, InFile="ThomasJefferson", 
InType="inaug", InTerm=1, President="Thomas Jefferson")
f.plotsent.len(In.list=sentence.list, InFile="AbrahamLincoln", 
InType="inaug", InTerm=1, President="Abraham Lincoln")
f.plotsent.len(In.list=sentence.list, InFile="RutherfordBHayes", 
InType="inaug", InTerm=1, President="Rutherford B. Hayes")

Then I am going to find some sentences that can have a good represent of the president’s characteristic

cat("\nGeorge Washingto\n")

George Washingto
speech.df=tbl_df(sentence.list.place)%>%
filter(File=="GeorgeWashington", type=="inaug", word.count>=4)%>%
select(sentences, anger:trust)
speech.df=as.data.frame(speech.df)
as.character(speech.df$sentences[apply(speech.df[,-1], 2, which.max)])
[1] "Previous to the execution of any official act of the President the Constitution requires an oath of office."                                                                                                                                                         
[2] "and since the preservation of the sacred fire of liberty and the destiny of the republican model of government are justly considered, perhaps, as deeply, as finally, staked on the experiment entrusted to the hands of the American people."                       
[3] "between the genuine maxims of an honest and magnanimous policy and the solid rewards of public prosperity and felicity;"                                                                                                                                             
[4] "Previous to the execution of any official act of the President the Constitution requires an oath of office."                                                                                                                                                         
[5] "I dwell on this prospect with every satisfaction which an ardent love for my country can inspire, since there is no truth more thoroughly established than that there exists in the economy and course of nature an indissoluble union between virtue and happiness;"
[6] "From this resolution I have in no instance departed;"                                                                                                                                                                                                                
[7] "Having thus imparted to you my sentiments as they have been awakened by the occasion which brings us together, I shall take my present leave;"                                                                                                                       
[8] "Previous to the execution of any official act of the President the Constitution requires an oath of office."                                                                                                                                                         
cat("\nThomas Jefferson\n")

Thomas Jefferson
speech.df=tbl_df(sentence.list.place)%>%
filter(File=="ThomasJefferson", type=="inaug", Term==1, word.count>=5)%>%
select(sentences, anger:trust)
speech.df=as.data.frame(speech.df)
as.character(speech.df$sentences[apply(speech.df[,-1], 2, which.max)])
[1] "the supremacy of the civil over the military authority;"                                 
[2] "economy in the public expense, that labor may be lightly burthened;"                     
[3] "peace, commerce, and honest friendship with all nations, entangling alliances with none;"
[4] "the supremacy of the civil over the military authority;"                                 
[5] "peace, commerce, and honest friendship with all nations, entangling alliances with none;"
[6] "peace, commerce, and honest friendship with all nations, entangling alliances with none;"
[7] "the supremacy of the civil over the military authority;"                                 
[8] "peace, commerce, and honest friendship with all nations, entangling alliances with none;"
cat("\nAbraham Lincoln\n")

Abraham Lincoln
speech.df=tbl_df(sentence.list.place)%>%
filter(File=="AbrahamLincoln", type=="inaug", Term==1, word.count>=4)%>%
select(sentences, anger:trust)
speech.df=as.data.frame(speech.df)
as.character(speech.df$sentences[apply(speech.df[,-1], 2, which.max)])
[1] "Whoever rejects it does of necessity fly to anarchy or to despotism."                        
[2] "In our present differences, is either party without faith of being in the right?"            
[3] "'May' Congress prohibit slavery in the Territories?"                                         
[4] "The Government will not assail 'you'."                                                       
[5] "Though passion may have strained it must not break our bonds of affection."                  
[6] "Whoever rejects it does of necessity fly to anarchy or to despotism."                        
[7] "The Government will not assail 'you'."                                                       
[8] "Perpetuity is implied, if not expressed, in the fundamental law of all national governments."
cat("\nRutherford B. Hayes\n")

Rutherford B. Hayes
speech.df=tbl_df(sentence.list.place)%>%
filter(File=="RutherfordBHayes", type=="inaug", Term==1, word.count>=5)%>%
select(sentences, anger:trust)
speech.df=as.data.frame(speech.df)
as.character(speech.df$sentences[apply(speech.df[,-1], 2, which.max)])
[1] "Many of the calamitous efforts of the tremendous revolution which has passed over the Southern States still remain."                                                                                                                                                                                                                                                                                 
[2] "They neither expected nor desired from public officers any partisan service."                                                                                                                                                                                                                                                                                                                        
[3] "That tribunal--established by law for this sole purpose;"                                                                                                                                                                                                                                                                                                                                            
[4] "That tribunal--established by law for this sole purpose;"                                                                                                                                                                                                                                                                                                                                            
[5] "The circumstances were, perhaps, in no respect extraordinary save in the closeness and the consequent uncertainty of the result."                                                                                                                                                                                                                                                                    
[6] "That it was a wise, just, and providential act, fraught with good for all concerned, is not generally conceded throughout the country."                                                                                                                                                                                                                                                              
[7] "If, unhappily, questions of difference should at any time during the period of my Administration arise between the United States and any foreign government, it will certainly be my disposition and my hope to aid in their settlement in the same peaceful and honorable way, thus securing to our country the great blessings of peace and mutual good offices with all the nations of the world."
[8] "That tribunal--established by law for this sole purpose;"                                                                                                                                                                                                                                                                                                                                            

Clustering of emotions

heatmap.2(cor(sentence.list%>%filter(type=="inaug")%>%select(anger:trust)), 
scale = "none", 
col = bluered(100), , margin=c(6, 6), key=F,
trace = "none", density.info = "none")
par(mar=c(4, 6, 2, 1))
emo.means.north=colMeans(select(sentence.list.place%>%filter(Places=="N"), anger:trust)>0.01)
emo.means.south=colMeans(select(sentence.list.place%>%filter(Places=="S"), anger:trust)>0.01)
col.use=c("red2", "darkgoldenrod1", 
"chartreuse3", "blueviolet",
"darkgoldenrod2", "dodgerblue3", 
"darkgoldenrod1", "darkgoldenrod1")
par(mfrow=c(1,2))

barplot(emo.means.north[order(emo.means.north)], las=2, col=col.use[order(emo.means.north)], horiz=T, main="North likely")
barplot(emo.means.south[order(emo.means.south)], las=2, col=col.use[order(emo.means.south)], horiz=T, main="South likely")

presid.summary=tbl_df(sentence.list.place)%>%
filter(type=="inaug",)%>%
#group_by(paste0(type, File))%>%
group_by(Filedirection)%>%
summarise(
anger=mean(anger),
anticipation=mean(anticipation),
disgust=mean(disgust),
fear=mean(fear),
joy=mean(joy),
sadness=mean(sadness),
surprise=mean(surprise),
trust=mean(trust)
#negative=mean(negative),
#positive=mean(positive)
)
presid.summary=as.data.frame(presid.summary)
rownames(presid.summary)=as.character((presid.summary[,1]))
km.res=kmeans(presid.summary[,-1], iter.max=200,
5)
fviz_cluster(km.res, 
stand=F, repel= TRUE,
data = presid.summary[,-1], xlab="", xaxt="n",
show.clust.cent=FALSE)

LDA Data analysis

For topic modeling, we prepare a corpus of sentence snipets as follows. For each speech, we start with sentences and prepare a snipet with a given sentence with the flanking sentences.

sentence.list<-sentence.list.place
corpus.list=sentence.list[2:(nrow(sentence.list)-1), ]
sentence.pre=sentence.list$sentences[1:(nrow(sentence.list)-2)]
sentence.post=sentence.list$sentences[3:(nrow(sentence.list)-1)]
corpus.list$snipets=paste(sentence.pre, corpus.list$sentences, sentence.post, sep=" ")
rm.rows=(1:nrow(corpus.list))[corpus.list$sent.id==1]
rm.rows=c(rm.rows, rm.rows-1)
corpus.list=corpus.list[-rm.rows, ]

Text mining

docs <- Corpus(VectorSource(corpus.list$snipets))
writeLines(as.character(docs[[sample(1:nrow(corpus.list), 1)]]))
Here too experience has afforded us the most satisfactory proof in its favor. Just as this Constitution was put into action several of the principal States of Europe had become much agitated and some of them seriously convulsed. Destructive wars ensued, which have of late only been terminated.
#remove potentially problematic symbols
docs <-tm_map(docs,content_transformer(tolower))
writeLines(as.character(docs[[sample(1:nrow(corpus.list), 1)]]))
the sagacious mind of mr. jefferson early saw and lamented this error, and attempts have been made, hitherto without success, to apply the amendatory power of the states to its correction. as, however, one mode of correction is in the power of every president, and consequently in mine, it would be useless, and perhaps invidious, to enumerate the evils of which, in the opinion of many of our fellow-citizens, this error of the sages who framed the constitution may have been the source and the bitter fruits which we are still to gather from it if it continues to disfigure our system.
#remove punctuation
docs <- tm_map(docs, removePunctuation)
writeLines(as.character(docs[[sample(1:nrow(corpus.list), 1)]]))
others in my judgment are attributable to a misconstruction of some of its provisions of the former is the eligibility of the same individual to a second term of the presidency the sagacious mind of mr
#Strip digits
docs <- tm_map(docs, removeNumbers)
writeLines(as.character(docs[[sample(1:nrow(corpus.list), 1)]]))
in justly balancing the powers of the federal and state authorities difficulties nearly insurmountable arose at the outset and subsequent collisions were deemed inevitable amid these it was scarcely believed possible that a scheme of government so complex in construction could remain uninjured from time to time embarrassments have certainly occurred
#remove stopwords
docs <- tm_map(docs, removeWords, stopwords("english"))
writeLines(as.character(docs[[sample(1:nrow(corpus.list), 1)]]))
    highly favored condition   country    interest  every citizen  maintain     dangers  menace us   exist     ascertained  guarded 
#remove whitespace
docs <- tm_map(docs, stripWhitespace)
writeLines(as.character(docs[[sample(1:nrow(corpus.list), 1)]]))
 territory enlarged fair honorable treaty great advantage original states states respectively protected national government mild parental system foreign dangers enjoying within separate spheres wise partition power just proportion sovereignty improved police extended settlements attained strength maturity best proofs wholesome laws well administered look condition individuals proud spectacle exhibit
#Stem document
docs <- tm_map(docs,stemDocument)
writeLines(as.character(docs[[sample(1:nrow(corpus.list), 1)]]))
made recommend pledg public exig requir recurr time remain trust equal promptitud perform duti alik incumb experi now make will seen next session congress whether revenu shall augment adequ necessari purpos defici still continu especi probabl perman cours pursu appear obvious

Topic modeling

Gengerate document-term matrices.

dtm <- DocumentTermMatrix(docs)
#convert rownames to filenames#convert rownames to filenames
rownames(dtm) <- paste(corpus.list$type, corpus.list$File,
corpus.list$Term, corpus.list$sent.id, sep="_")
rowTotals <- apply(dtm , 1, sum) #Find the sum of words in each Document
dtm  <- dtm[rowTotals> 0, ]
corpus.list=corpus.list[rowTotals>0, ]

Run LDA

#Set parameters for Gibbs sampling
burnin <- 4000
iter <- 2000
thin <- 500
seed <-list(2003,5,63,100001,765)
nstart <- 5
best <- TRUE
#Number of topics
k <- 15
#Run LDA using Gibbs sampling
ldaOut <-LDA(dtm, k, method="Gibbs", control=list(nstart=nstart, seed = seed, best=best,burnin = burnin, iter = iter, thin=thin))
#write out results
#docs to topics
ldaOut.topics <- as.matrix(topics(ldaOut))
table(c(1:k, ldaOut.topics))

  1   2   3   4   5   6   7   8   9  10  11  12  13  14  15 
149 146 178 131 155 156 168 162 113 129 147 152 145 152 120 
write.csv(ldaOut.topics,
          file=paste("../out/LDAGibbs",k,"DocsToTopics.csv"))
#top 6 terms in each topic
ldaOut.terms <- as.matrix(terms(ldaOut,20))
write.csv(ldaOut.terms,
          file=paste("../out/LDAGibbs",k,"TopicsToTerms.csv"))
#probabilities associated with each topic assignment
topicProbabilities <- as.data.frame(ldaOut@gamma)
write.csv(topicProbabilities,file=paste("/Users/westspringamerica/Downloads/wk2-TextMining/out/LDAGibbs",k,"TopicProbabilities.csv"))
terms.beta=ldaOut@beta
terms.beta=scale(terms.beta)
topics.terms=NULL
for(i in 1:k){
topics.terms=rbind(topics.terms, ldaOut@terms[order(terms.beta[i,], decreasing = TRUE)[1:7]])
}
topics.terms
      [,1]       [,2]        [,3]         [,4]        [,5]         [,6]        [,7]           
 [1,] "knowledg" "appeal"    "district"   "insist"    "process"    "dream"     "alter"        
 [2,] "portion"  "industri"  "agricultur" "indian"    "tariff"     "discrimin" "foster"       
 [3,] "station"  "oath"      "presenc"    "obedi"     "overwhelm"  "dilig"     "shrink"       
 [4,] "path"     "preced"    "repeat"     "announc"   "occurr"     "weigh"     "seced"        
 [5,] "cours"    "friend"    "intercours" "allianc"   "negoti"     "diplomaci" "kindr"        
 [6,] "armi"     "invas"     "late"       "militia"   "thousand"   "battl"     "compel"       
 [7,] "unit"     "territori" "weak"       "dominion"  "everyth"    "western"   "discourag"    
 [8,] "sphere"   "endang"    "tend"       "discord"   "impli"      "contend"   "discountenanc"
 [9,] "appoint"  "reform"    "promis"     "partisan"  "conveni"    "compens"   "color"        
[10,] "intellig" "corrupt"   "broad"      "descend"   "comprehens" "victori"   "scope"        
[11,] "doubt"    "economi"   "soon"       "credit"    "contract"   "privat"    "payment"      
[12,] "decis"    "class"     "decid"      "imperfect" "obey"       "deliv"     "stake"        
[13,] "legisl"   "grant"     "major"      "earli"     "languag"    "conform"   "conceiv"      
[14,] "father"   "restor"    "god"        "fruit"     "mankind"    "fortun"    "ardent"       
[15,] "injuri"   "roman"     "resist"     "bosom"     "democraci"  "introduc"  "aristocraci"  
ldaOut.terms
      Topic 1    Topic 2      Topic 3         Topic 4     Topic 5         Topic 6     Topic 7     Topic 8     Topic 9    
 [1,] "right"    "interest"   "duti"          "will"      "nation"        "war"       "state"     "govern"    "shall"    
 [2,] "upon"     "protect"    "confid"        "principl"  "peac"          "made"      "unit"      "union"     "will"     
 [3,] "citizen"  "within"     "may"           "now"       "foreign"       "place"     "territori" "state"     "offic"    
 [4,] "equal"    "duti"       "trust"         "great"     "interest"      "without"   "great"     "constitut" "civil"    
 [5,] "everi"    "revenu"     "countri"       "import"    "justic"        "forc"      "increas"   "power"     "servic"   
 [6,] "american" "limit"      "fellowcitizen" "countri"   "respect"       "great"     "extend"    "general"   "polit"    
 [7,] "secur"    "make"       "best"          "upon"      "countri"       "necessari" "new"       "form"      "give"     
 [8,] "person"   "far"        "high"          "part"      "relat"         "sinc"      "mani"      "preserv"   "expect"   
 [9,] "without"  "portion"    "faith"         "may"       "polici"        "time"      "popul"     "exercis"   "administr"
[10,] "enjoy"    "industri"   "whose"         "year"      "power"         "purpos"    "independ"  "feder"     "effort"   
[11,] "condit"   "encourag"   "take"          "opinion"   "honor"         "defens"    "limit"     "object"    "public"   
[12,] "found"    "product"    "respons"       "parti"     "maintain"      "resourc"   "remain"    "institut"  "support"  
[13,] "possess"  "use"        "call"          "subject"   "just"          "progress"  "becom"     "author"    "influenc" 
[14,] "act"      "commerc"    "shall"         "conduct"   "cours"         "land"      "less"      "system"    "need"     
[15,] "can"      "home"       "feel"          "sentiment" "well"          "might"     "except"    "whole"     "purpos"   
[16,] "posit"    "manufactur" "discharg"      "elect"     "friend"        "event"     "whole"     "domest"    "best"     
[17,] "rest"     "countri"    "oblig"         "made"      "desir"         "suffici"   "commerc"   "concern"   "appoint"  
[18,] "privileg" "benefit"    "just"          "depend"    "intercours"    "militari"  "near"      "individu"  "reform"   
[19,] "suffer"   "find"       "sens"          "administr" "fellowcitizen" "work"      "vast"      "harmoni"   "proper"   
[20,] "advantag" "mean"       "success"       "accord"    "preserv"       "armi"      "enlarg"    "common"    "promot"   
      Topic 10     Topic 11     Topic 12   Topic 13     Topic 14    Topic 15  
 [1,] "peopl"      "public"     "law"      "constitut"  "happi"     "spirit"  
 [2,] "govern"     "will"       "one"      "power"      "hope"      "exist"   
 [3,] "can"        "may"        "can"      "execut"     "prosper"   "everi"   
 [4,] "free"       "secur"      "question" "congress"   "bless"     "peopl"   
 [5,] "nation"     "requir"     "differ"   "effect"     "futur"     "continu" 
 [6,] "human"      "measur"     "view"     "legisl"     "look"      "danger"  
 [7,] "present"    "demand"     "practic"  "depart"     "let"       "institut"
 [8,] "mind"       "debt"       "section"  "upon"       "liberti"   "time"    
 [9,] "hand"       "govern"     "must"     "grant"      "still"     "caus"    
[10,] "among"      "doubt"      "parti"    "control"    "even"      "liberti" 
[11,] "natur"      "experi"     "opinion"  "presid"     "world"     "result"  
[12,] "intellig"   "necessari"  "case"     "instrument" "year"      "patriot" 
[13,] "noth"       "faith"      "good"     "author"     "establish" "long"    
[14,] "repres"     "provid"     "may"      "might"      "patriot"   "consequ" 
[15,] "love"       "expenditur" "claim"    "act"        "fear"      "true"    
[16,] "order"      "money"      "other"    "given"      "present"   "republ"  
[17,] "enlighten"  "everi"      "anoth"    "major"      "father"    "chang"   
[18,] "virtu"      "return"     "believ"   "howev"      "man"       "system"  
[19,] "republican" "economi"    "decis"    "becom"      "countri"   "injuri"  
[20,] "men"        "due"        "provis"   "first"      "exampl"    "none"    

Based on the most popular terms and the most salient terms for each topic, we assign a hashtag to each topic. This part require manual setup as the topics are likely to change.

topics.oldhash=c("Economy", "America", "Defense", "Belief", "Election", "Patriotism", "Unity", "Government", "Reform", "Temporal", "WorkingFamilies", "Freedom", "Equality", "Misc", "Legislation")
topicsnew.hash=c("everi", "war" ,"law",  "upon","nation", "union", "constitut","will","public","interest","state",     "great","duti", "peopl","right")
topics.hash=topicsnew.hash
corpus.list$ldatopic=as.vector(ldaOut.topics)
corpus.list$ldahash=topics.hash[ldaOut.topics]
colnames(topicProbabilities)=topics.hash
corpus.list.df=cbind(corpus.list, topicProbabilities)

Clustering of topics

par(mar=c(1,1,1,1))
topic.summary=tbl_df(corpus.list.df)%>%
filter(type%in%c("inaug"))%>%
select(Filedirection, everi: right)%>%
group_by(Filedirection)%>%
summarise_each(funs(mean))
`summarise_each()` is deprecated.
Use `summarise_all()`, `summarise_at()` or `summarise_if()` instead.
To map `funs` over all variables, use `summarise_all()`
topic.summary=as.data.frame(topic.summary)
rownames(topic.summary)=topic.summary[,1]
topic.plot=c(1:15)
print(topics.hash[topic.plot])
 [1] "everi"     "war"       "law"       "upon"      "nation"    "union"     "constitut" "will"      "public"    "interest" 
[11] "state"     "great"     "duti"      "peopl"     "right"    
heatmap.2(as.matrix(topic.summary[,topic.plot+1]), 
scale = "column", key=F, 
col = bluered(100),
cexRow = 0.8, cexCol = 0.9, margins = c(8, 8),
trace = "none", density.info = "none")

    
par(mfrow=c(5, 1), mar=c(1,1,2,0), bty="n", xaxt="n", yaxt="n")
topic.plot=c(1, 13, 14, 15, 8, 9, 12)
print(topics.hash[topic.plot])
[1] "everi"  "duti"   "peopl"  "right"  "will"   "public" "great" 
speech.df=tbl_df(corpus.list.df)%>%filter(File=="GeorgeWashington", type=="inaug",Term==1)%>%select(sent.id, everi: right)
speech.df=as.matrix(speech.df)
speech.df[,-1]=replace(speech.df[,-1], speech.df[,-1]<1/15, 0.001)
speech.df[,-1]=f.smooth.topic(x=speech.df[,1], y=speech.df[,-1])
plot.stacked(speech.df[,1], speech.df[,topic.plot+1], 
xlab="Sentences", ylab="Topic share", main="GeorgeWashington")
[1] 0.05298456 0.10596912 0.15895368 0.21193824 0.26492280 0.31790736 0.37089192
speech.df=tbl_df(corpus.list.df)%>%filter(File=="ThomasJefferson", type=="inaug", Term==1)%>%select(sent.id, everi: right)
speech.df=as.matrix(speech.df)
speech.df[,-1]=replace(speech.df[,-1], speech.df[,-1]<1/15, 0.001)
speech.df[,-1]=f.smooth.topic(x=speech.df[,1], y=speech.df[,-1])
plot.stacked(speech.df[,1], speech.df[,topic.plot+1],
xlab="Sentences", ylab="Topic share", main="ThomasJefferson")
[1] 0.06071925 0.12143850 0.18215775 0.24287700 0.30359625 0.36431550 0.42503475
speech.df=tbl_df(corpus.list.df)%>%filter(File=="UlyssesSGrant", type=="inaug", Term==1)%>%select(sent.id, everi: right)
speech.df=as.matrix(speech.df)
speech.df[,-1]=replace(speech.df[,-1], speech.df[,-1]<1/15, 0.001)
speech.df[,-1]=f.smooth.topic(x=speech.df[,1], y=speech.df[,-1])
plot.stacked(speech.df[,1], speech.df[,topic.plot+1], 
xlab="Sentences", ylab="Topic share", main="UlyssesSGrant")
[1] 0.05193823 0.10387646 0.15581469 0.20775292 0.25969115 0.31162938 0.36356761
speech.df=tbl_df(corpus.list.df)%>%filter(File=="AbrahamLincoln", type=="inaug", Term==1)%>%select(sent.id, everi: right)
speech.df=as.matrix(speech.df)
speech.df[,-1]=replace(speech.df[,-1], speech.df[,-1]<1/15, 0.001)
speech.df[,-1]=f.smooth.topic(x=speech.df[,1], y=speech.df[,-1])
plot.stacked(speech.df[,1], speech.df[,topic.plot+1],
xlab="Sentences", ylab="Topic share", main="AbrahamLincoln")
[1] 0.06509839 0.13019677 0.19529516 0.26039354 0.32549193 0.39059031 0.45568870
speech.df=tbl_df(corpus.list.df)%>%filter(File=="JamesMonroe", type=="inaug",Term==1)%>%select(sent.id, everi: right)
speech.df=as.matrix(speech.df)
speech.df[,-1]=replace(speech.df[,-1], speech.df[,-1]<1/15, 0.001)
speech.df[,-1]=f.smooth.topic(x=speech.df[,1], y=speech.df[,-1])
plot.stacked(speech.df[,1], speech.df[,topic.plot+1],
xlab="Sentences", ylab="Topic share", main="JamesMonroe")
[1] 0.05186465 0.10372929 0.15559394 0.20745859 0.25932323 0.31118788 0.36305253

presid.summary=tbl_df(corpus.list.df)%>%
filter(type=="inaug")%>%
select(Filedirection, everi: right)%>%
group_by(Filedirection)%>%
summarise_each(funs(mean))
`summarise_each()` is deprecated.
Use `summarise_all()`, `summarise_at()` or `summarise_if()` instead.
To map `funs` over all variables, use `summarise_all()`
presid.summary=as.data.frame(presid.summary)
rownames(presid.summary)=as.character((presid.summary[,1]))
km.res=kmeans(scale(presid.summary[,-1]), iter.max=200,
5)
fviz_cluster(km.res, 
stand=T, repel= TRUE,
data = presid.summary[,-1],
show.clust.cent=FALSE)

Conclusions:

According to the analysis, we find that

When it comes to number of words in presidents’augural presentation, the south is not statistically different from the north, while they do speak a little shorter on average.

All presidents like to use the word “WIll”,maybe they are promising the audience with a good future or they would like to show his strong willingness. In early period “People” and “Government” has more chance to appear in the presentation than nowadays. Presidents from north like to say about “People”, while “South” is more likely to talk about States. This really make sense that Southerners want a more united States instead of a United States with a strong government. And the north people urge them to liberate people of colored races.

When evaluating emotions and length of Presidents,President lincoln’s passage are very colorful of rhythm and emotions, we know he is very good at giving speech. As a whole, northern presidents has more fear and sad feelings then the south,while the south are more joyful and likely to surpise, this may to due to coldness of the north making people sorrow while the south has more sunny weathers. the cluster is not good enough to give the overview of all presidents because each president has his own unique features

By topic modelling we find that the old topic are quite different from newer ones.and the heatmap are more clear to show there are southern and northern presidents seem to have some inner cores ,they may the same ancient synonym ancestry. and we also find the topics they are talking about are quite the same but not in the same form

Ci0tLQp0aXRsZTogV2hhdCBhcmUgZGlmZmVyZW5jZXMgYmV0d2VlbiBQcmVzaWRlbnQgZnJvbSB0aGUgU291dGggYW5kIE5vcnRoIGJlZm9yZSBjaXZpbHdhcj8Kb3V0cHV0OiBodG1sX25vdGVib29rCgotLS0KSW4gdGhpcyBwcm9qZWN0LCB3ZSB3YW50IHRvIGV4cGxvcmUgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgcHJlc2lkZW50IHRoYXQgaXMgcmFpc2VkIGFuZCBib3JuIGluIHRoZSBTb3V0aChzdGF0ZSB3aXRoIHNsYXZlcnkpIGFuZCBOb3J0aCwgU2luY2UgYWZ0ZXIgdGhlIGNpdmlsIHdhciB0aGUgY3VsdHVyYWwgYm91bmRhcnkgYmV0d2VlbiB0aGUgTm9ydGggYW5kIFNvdXRoIGhhdmUgYmVlbiBkaW1pbmlzaGVkLiBJIGp1c3QgY2hvb3NlIHByZXNpZGVudHMgZnJvbSBHZW9yZ2UgV2FzaGluZ3RvbiB0byBCZW5qYW1pbiBIYXJyaXNvbiwgdGhlIGxhc3QgcHJlc2lkZW50IHdobyBoYXMgYmVjYW1lIGFkdWx0IGJlZm9yZSBjaXZpbCB3YXIsYmFzZWQgb24gdGhlIGFzc3VtcHRpb25zIHRoYXQgcGVvcGxlcyBpZGVvbG9neSBhbmQgY2hhcmFjdGVyaXN0aWMgYXJlIGZvcm1lZCBpbiB0aGVpciBlYXJseSBhZHVsdGhvb2Qgc28gdGhleSBzaG91bGQgbm90IGJlIGluZmx1ZW5jZWQgYnkgcG9zdC13YXIgc2l0dWl0aW9ucyAKCgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KcGFja2FnZXMudXNlZD1jKCJydmVzdCIsICJ0aWJibGUiLCAicWRhcCIsIAogICAgICAgICAgICAgICAgInNlbnRpbWVudHIiLCAiZ3Bsb3RzIiwgImRwbHlyIiwKICAgICAgICAgICAgICAgICJ0bSIsICJzeXV6aGV0IiwgImZhY3RvZXh0cmEiLCAKICAgICAgICAgICAgICAgICJiZWVzd2FybSIsICJzY2FsZXMiLCAiUkNvbG9yQnJld2VyIiwKICAgICAgICAgICAgICAgICJSQU5OIiwgInRtIiwgInRvcGljbW9kZWxzIikKCiMgY2hlY2sgcGFja2FnZXMgdGhhdCBuZWVkIHRvIGJlIGluc3RhbGxlZC4KcGFja2FnZXMubmVlZGVkPXNldGRpZmYocGFja2FnZXMudXNlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgIGludGVyc2VjdChpbnN0YWxsZWQucGFja2FnZXMoKVssMV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFja2FnZXMudXNlZCkpCiMgaW5zdGFsbCBhZGRpdGlvbmFsIHBhY2thZ2VzCmlmKGxlbmd0aChwYWNrYWdlcy5uZWVkZWQpPjApewogIGluc3RhbGwucGFja2FnZXMocGFja2FnZXMubmVlZGVkLCBkZXBlbmRlbmNpZXMgPSBUUlVFKQp9CgojIGxvYWQgcGFja2FnZXMKCmxpYnJhcnkoInJ2ZXN0IikKbGlicmFyeSgidGliYmxlIikKbGlicmFyeSgicWRhcCIpCmxpYnJhcnkoInNlbnRpbWVudHIiKQpsaWJyYXJ5KCJncGxvdHMiKQpsaWJyYXJ5KCJkcGx5ciIpCmxpYnJhcnkoInRtIikKbGlicmFyeSgicG5nIikKbGlicmFyeSgic3l1emhldCIpCmxpYnJhcnkoImZhY3RvZXh0cmEiKQpsaWJyYXJ5KCJiZWVzd2FybSIpCmxpYnJhcnkoInNjYWxlcyIpCmxpYnJhcnkoIlJDb2xvckJyZXdlciIpCmxpYnJhcnkoIlJBTk4iKQpsaWJyYXJ5KCJ0bSIpCmxpYnJhcnkoInRvcGljbW9kZWxzIikKbGlicmFyeSgieGxzeCIpCmxpYnJhcnkoIndvcmRjbG91ZCIpCmxpYnJhcnkoInRpZHl0ZXh0IikKc291cmNlKCIuLi9saWIvcGxvdHN0YWNrZWQuUiIpCnNvdXJjZSgiLi4vbGliL3NwZWVjaEZ1bmNzLlIiKQpgYGAKVGhpcyBub3RlYm9vayB3YXMgcHJlcGFyZWQgd2l0aCB0aGUgZm9sbG93aW5nIGVudmlyb25tZW50YWwgc2V0dGluZ3MuCgpgYGB7cn0KcHJpbnQoUi52ZXJzaW9uKQpgYGAKI0RhdGEgSGFydmVzdAogd2Ugc2VsZWN0ZWQgYWxsIGluYXVndXJhbCBhZGRyZXNzZXMgb2YgcGFzdCBwcmVzaWRlbnRzLCBmb3IgbGFjayBvZiBkYXRhIG9mIG5vbWluYWwgYW5kIGZhcmV3ZWxsIGFkZHJlc3NlcyBvZiBwcmVzaWRlbnQgYmVmb3JlIGNpdmlsIHdhci4gCgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KIyMjIEluYXVndWFyYWwgc3BlZWNoZXMKbWFpbi5wYWdlIDwtIHJlYWRfaHRtbCh4ID0gImh0dHA6Ly93d3cucHJlc2lkZW5jeS51Y3NiLmVkdS9pbmF1Z3VyYWxzLnBocCIpCiMgR2V0IGxpbmsgVVJMcwojIGYuc3BlZWNobGlua3MgaXMgYSBmdW5jdGlvbiBmb3IgZXh0cmFjdGluZyBsaW5rcyBmcm9tIHRoZSBsaXN0IG9mIHNwZWVjaGVzLiAKaW5hdWc9Zi5zcGVlY2hsaW5rcyhtYWluLnBhZ2UpCiNoZWFkKGluYXVnKQojYXMuRGF0ZShpbmF1Z1ssMV0sIGZvcm1hdD0iJUIgJWUsICVZIikKaW5hdWc9aW5hdWdbLW5yb3coaW5hdWcpLF0gIyByZW1vdmUgdGhlIGxhc3QgbGluZSwgaXJyZWxldmFudCBkdWUgdG8gZXJyb3IuCgpgYGAKClVzaW5nIHNwZWVjaCBtZXRhZGF0YSBwb3N0ZWQgb24gPGh0dHA6Ly93d3cucHJlc2lkZW5jeS51Y3NiLmVkdS8+LCBXZSBwcmVwYXJlZCB4bHN4IGRhdGEgc2V0cyBmb3IgdGhlIHNwZWVjaGVzIHdlIHdpbGwgc2NyYXAuIApgYGB7cn0KcGljdHVyZSA8LSByZWFkUE5HKCJtYXAucG5nIikKZ3JpZDo6Z3JpZC5yYXN0ZXIocGljdHVyZSkKI3Bsb3QocGljdHVyZSkKYGBgClRoaXMgaXMgdGhlIGRhdGEgSSBoYXZlIHByb2Nlc3NlZC4gSSBqdXN0IGNob29zZSBwcmVzaWRlbnRzIGZyb20gR2VvcmdlIFdhc2hpbmd0b24gdG8gQmVuamFtaW4gSGFycmlzb24sIHRoZSBsYXN0IHByZXNpZGVudCB3aG8gaGFzIGJlY2FtZSBhZHVsdCBiZWZvcmUgY2l2aWwgd2FyLCBiYXNlZCBvbiB0aGUgYXNzdW1wdGlvbnMgdGhhdCBwZW9wbGVzIGlkZW9sb2d5IGFuZCBjaGFyYWN0ZXJpc3RpYyBhcmUgZm9ybWVkIGluIHRoZWlyIGVhcmx5IGFkdWx0aG9vZCBzbyB0aGV5IHNob3VsZCBub3QgYmUgaW5mbHVlbmNlZCBieSBwb3N0LXdhciBuZXcgaWRlb2xvZ3kgYW5kIGltcGFjdHMuCgpBYm91dCBvbmUtdGhpcmQgcHJlc2lkZW50cyB3ZXJlIGJvcm4gYW5kIHJhaXNlZCBpbiB0aGUgU291dGgsIHdoaWxlIHRoZSBvdGhlcnMgd2VyZSByYWlzZWQgaW4gdGhlIE5vcnRoIHBhcnQgb2YgQW1lcmljYS4gV2UgdXNlIHRoZSBjb21tb24gTWFzb27igJNEaXhvbiBsaW5lIHRvIHNlcGVyYXRlIHNvdXRoIGFuZCBub3J0aCBhcyBtb3N0IHBlb3BsZSBkby4gSW4gdGhlIFNvdXRoLCBtb3N0IFByZXNpZGVudHMgYXJlIGZyb20gVmlyZ2luaWEgYW5kIFRlbm5lc3NlZSwgIGluIHRoZSBOb3J0aCB0aGVyZSBhcmUgUHJlc2lkZW50cyBmcm9tIE5ldyBFbmdsYW5kLCBOZXcgWW9yayAsIGlJbGlub2lzIGV0YwoKYGBge3J9CgppbmF1Zy5saXN0ID0gcmVhZC54bHN4KCIuLi9kYXRhL2luYXVnbGlzdF9wbGFjZS54bHN4Iiwgc2hlZXRJbmRleCA9IDEpCmBgYAoKV2UgYXNzZW1ibGUgYWxsIHNjcmFwcGVkIHNwZWVjaGVzIGludG8gb25lIGxpc3QuIE5vdGUgaGVyZSB0aGF0IHdlIGRvbnQgaGF2ZSB0aGUgZnVsbCB0ZXh0IHlldCwgb25seSB0aGUgbGlua3MgdG8gZnVsbCB0ZXh0IHRyYW5zY3JpcHRzLiAKc2NyYXAgdGhlIHRleHRzIG9mIHNwZWVjaGVzIGZyb20gdGhlIHNwZWVjaCBVUkxzLgoKYGBge3J9CmluYXVnLmxpc3QkdHlwZT1jKHJlcCgiaW5hdWciLCBucm93KGluYXVnLmxpc3QpKSkKaW5hdWcubGlzdD1jYmluZChpbmF1Zy5saXN0LGluYXVnKQpgYGAKCkJhc2VkIG9uIHRoZSBsaXN0IG9mIHNwZWVjaGVzLCB3ZSBzY3JhcCB0aGUgbWFpbiB0ZXh0IHBhcnQgb2YgdGhlIHRyYW5zY3JpcHQncyBodG1sIHBhZ2UuIEZvciBzaW1wbGUgaHRtbCBwYWdlcyBvZiB0aGlzIGtpbmQuIEZvciByZXByb2R1Y2liaWxpdHksIHdlIGFsc28gc2F2ZSBvdXIgc2NyYXBwZWQgc3BlZWNoZXMgaW50byBvdXIgbG9jYWwgZm9sZGVyIGFzIGluZGl2aWR1YWwgc3BlZWNoIGZpbGVzLiAKCk5vdyB3ZSBjb21iaW5lIHRoZSBpbmZvcm1hdGlvbiBmcm9tIHRoZSBpbnRlcm5ldCBhbmQgZGF0YXNldCwgY29tYmluZSB0aGUgY29sdW1ucyBvZiBpbXBvcnRhbnQgZGF0YSBmcmFtZSB0byBnZW5lcmF0ZSBmdXJ0aGVyIHVzZWZ1bCBpbmZvcm1hdGlvbiwgZmlyc3QgY29tYmluZSB0aGUgaHRtbCBhbmQgZGF0YSBhbmQgdGhlbiBkb3dubG9hZCBzY3JpcHRzIHRvIGxvY2FsIHJlcG9zaXRvcnkuCgpgYGB7cn0KIyBMb29wIG92ZXIgZWFjaCByb3cgaW4gc3BlZWNoLmxpc3QKaW5hdWcubGlzdCRmdWxsdGV4dD1OQQpmb3IoaSBpbiBzZXEobnJvdyhpbmF1Zy5saXN0KSkpIHsKICB0ZXh0IDwtIHJlYWRfaHRtbChpbmF1Zy5saXN0JHVybHNbaV0pICU+JSAjIGxvYWQgdGhlIHBhZ2UKICAgIGh0bWxfbm9kZXMoIi5kaXNwbGF5dGV4dCIpICU+JSAjIGlzbG9hdGUgdGhlIHRleHQKICAgIGh0bWxfdGV4dCgpICMgZ2V0IHRoZSB0ZXh0CmluYXVnLmxpc3QkZnVsbHRleHRbaV09dGV4dAoKICAjIENyZWF0ZSB0aGUgZmlsZSBuYW1lCiAjZmlsZW5hbWUgPC0gcGFzdGUwKCIuLi9kYXRhL2luYXVndXJhbHMvIiwgCiNpZihpbmF1Zy5saXN0JEZpbGVbaV0laW4lIG5vdXUpI2xldmVscyhzZW50ZW5jZXAubGlzdC5wbGFjZSRGaWxlKSkKI3sKICBmaWxlbmFtZSA8LSBwYXN0ZTAoIi4uL2RhdGEvaW5hdWd1cmFscy8iLCAKICAgICAgICAgICAgICAgICAgICAgaW5hdWcubGlzdCR0eXBlW2ldLAogICAgICAgICAgICAgICAgICAgICBpbmF1Zy5saXN0JEZpbGVbaV0sICItIiwgCiAgICAgICAgICAgICAgICAgICAgIGluYXVnLmxpc3QkVGVybVtpXSwgIi50eHQiKQogIHNpbmsoZmlsZSA9IGZpbGVuYW1lKSAlPiUgIyBvcGVuIGZpbGUgdG8gd3JpdGUgCiAgICBjYXQodGV4dCkgICMgd3JpdGUgdGhlIGZpbGUKICBzaW5rKCkgIyBjbG9zZSB0aGUgZmlsZQojfQp9CmBgYAoKV2Ugd2lsbCB1c2Ugc2VudGVuY2VzIGFzIHVuaXRzIG9mIGFuYWx5c2lzIGZvciB0aGlzIHByb2plY3QsIGFzIHNlbnRlbmNlcyBhcmUgbmF0dXJhbCBsYW5ndWdlIHVuaXRzIGZvciBvcmdhbml6aW5nIHRob3VnaHRzIGFuZCBpZGVhcy4gRm9yIGVhY2ggZXh0cmFjdGVkIHNlbnRlbmNlLCB3ZSBhcHBseSBzZW50aW1lbnQgYW5hbHlzaXMgdXNpbmcgTlJDIHNlbnRpbWVudC4gIlRoZSBOUkMgRW1vdGlvbiBMZXhpY29uIGlzIGEgbGlzdCBvZiBFbmdsaXNoIHdvcmRzIGFuZCB0aGVpciBhc3NvY2lhdGlvbnMgd2l0aCBlaWdodCBiYXNpYyBlbW90aW9ucyAoYW5nZXIsIGZlYXIsIGFudGljaXBhdGlvbiwgdHJ1c3QsIHN1cnByaXNlLCBzYWRuZXNzLCBqb3ksIGFuZCBkaXNndXN0KSBhbmQgdHdvIHNlbnRpbWVudHMgKG5lZ2F0aXZlIGFuZCBwb3NpdGl2ZSkuIFRoZSBhbm5vdGF0aW9ucyB3ZXJlIG1hbnVhbGx5IGRvbmUgYnkgY3Jvd2Rzb3VyY2luZy4iCgpXZSBhc3NpZ24gYW4gc2VxdWVudGlhbCBpZCB0byBlYWNoIHNlbnRlbmNlIGluIGEgc3BlZWNoIChgc2VudC5pZGApIGFuZCBhbHNvIGNhbGN1bGF0ZWQgdGhlIG51bWJlciBvZiB3b3JkcyBpbiBlYWNoIHNlbnRlbmNlIGFzICpzZW50ZW5jZSBsZW5ndGgqIChgd29yZC5jb3VudGApLgoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnNlbnRlbmNlLmxpc3Q9TlVMTAoKZm9yKGkgaW4gMTpucm93KGluYXVnLmxpc3QpKXsKICBzZW50ZW5jZXM9c2VudF9kZXRlY3QoaW5hdWcubGlzdCRmdWxsdGV4dFtpXSwKICAgICAgICAgICAgICAgICAgICAgICAgZW5kbWFya3MgPSBjKCI/IiwgIi4iLCAiISIsICJ8IiwiOyIpKQogIGlmKGxlbmd0aChzZW50ZW5jZXMpPjApewogICAgZW1vdGlvbnM9Z2V0X25yY19zZW50aW1lbnQoc2VudGVuY2VzKQogICAgd29yZC5jb3VudD13b3JkX2NvdW50KHNlbnRlbmNlcykKICAgICMgY29sbmFtZXMoZW1vdGlvbnMpPXBhc3RlMCgiZW1vLiIsIGNvbG5hbWVzKGVtb3Rpb25zKSkKICAgICMgaW4gY2FzZSB0aGUgd29yZCBjb3VudHMgYXJlIHplcm9zPwogICAgZW1vdGlvbnM9ZGlhZygxLyh3b3JkLmNvdW50KzAuMDEpKSUqJWFzLm1hdHJpeChlbW90aW9ucykKICAgIHNlbnRlbmNlLmxpc3Q9cmJpbmQoc2VudGVuY2UubGlzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgIGNiaW5kKGluYXVnLmxpc3RbaSwtbmNvbChpbmF1Zy5saXN0KV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbnRlbmNlcz1hcy5jaGFyYWN0ZXIoc2VudGVuY2VzKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmQuY291bnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVtb3Rpb25zLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW50LmlkPTE6bGVuZ3RoKHNlbnRlbmNlcykKICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgKQogIH0KfQpgYGAKClNvbWUgbm9uLXNlbnRlbmNlcyBleGlzdCBpbiByYXcgZGF0YSBkdWUgdG8gZXJyb25lb3VzIGV4dHJhIGVuZC1vZi1zZW50ZW5jZSBtYXJrcy4gQW5kIHdlIGFsc28gZGVsZXRlIHByZXNpZGVudHMgdGhhdCBkbyBub3QgYmVsb25nIHRvIG91ciBDYXRlZ29yeS4KYGBge3J9CnNlbnRlbmNlLmxpc3Q9c2VudGVuY2UubGlzdCU+JWZpbHRlcighaXMubmEod29yZC5jb3VudCkpIAoKc2VudGVuY2UubGlzdC5wbGFjZTwtc2VudGVuY2UubGlzdFthcy5sb2dpY2FsKDEtaXMubmEoc2VudGVuY2UubGlzdCRQbGFjZXMpKSxdCmBgYAoKRGF0YSBhbmFseXNpcyAtLS0gbGVuZ3RoIG9mIHNlbnRlbmNlcwoKRm9yIHNpbXBsZXIgdmlzdWFsaXphdGlvbiwgd2UgY2hvc2UgYSBzdWJzZXQgb2YgYmV0dGVyIGtub3duIHByZXNpZGVudHMgb3IgcHJlc2lkZW50aWFsIGNhbmRpZGF0ZXMgb24gd2hpY2ggdG8gZm9jdXMgb3VyIGFuYWx5c2lzLiAKTGV0IHVzIGhhdmVPdmVydmlldyBvZiBzZW50ZW5jZSBsZW5ndGggZGlzdHJpYnV0aW9uIGJ5IGRpZmZlcmVudCB0eXBlcyBvZiBzcGVlY2hlcy4gbGV0IHVzIHNlZSBob3cgcHJlc2lkZW50cyBpbmF1Z3VyYWwgbGVuZ3RoIGZyb20gZGlmZmVyZW50IHJlZ2lvbnMgZGlmZmVyCgppbmF1Z3VyYWwgc3BlZWNoZXMgCgoKYGBge3IsIGZpZy53aWR0aCA9IDMsIGZpZy5oZWlnaHQgPSAzfQoKcGFyKG1hcj1jKDQsIDExLCAyLCAyKSkKCgpzZW50ZW5jZS5saXN0LnBsYWNlJEZpbGU9ZmFjdG9yKHNlbnRlbmNlLmxpc3QucGxhY2UkRmlsZSkKCnNlbnRlbmNlLmxpc3QucGxhY2UkRmlsZU9yZGVyZWQ9cmVvcmRlcihzZW50ZW5jZS5saXN0LnBsYWNlJEZpbGUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbnRlbmNlLmxpc3QucGxhY2Ukd29yZC5jb3VudCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXI9VCkKCgojIHRoaXMgaXMgZm9yIGVhY2ggcHJlc2lkZW50CnNlbnRlbmNlLmxpc3QucGxhY2UkRmlsZWRpcmVjdGlvbj1wYXN0ZShzZW50ZW5jZS5saXN0LnBsYWNlJEZpbGVPcmRlcmVkLHNlbnRlbmNlLmxpc3QucGxhY2UkUGxhY2VzKQpiZWVzd2FybSh3b3JkLmNvdW50fkZpbGVkaXJlY3Rpb24sIAogICAgICAgICBkYXRhPXNlbnRlbmNlLmxpc3QucGxhY2UsCiAgICAgICAgIGhvcml6b250YWwgPSBUUlVFLCAKICAgICAgICAgcGNoPTE2LCAKICAgICAgICAgY29sPWFscGhhKGJyZXdlci5wYWwoOSwgIlNldDEiKSwgMC42KSwgCiAgICAgICAgIGNleD0wLjU1LCBjZXguYXhpcz0wLjgsIGNleC5sYWI9MC44LAogICAgICAgICBzcGFjaW5nPTUvbmxldmVscyhzZW50ZW5jZS5saXN0LnBsYWNlJEZpbGVPcmRlcmVkKSwKICAgICAgICAgbGFzPTIsIHhsYWI9Ik51bWJlciBvZiB3b3JkcyBpbiBhIHNlbnRlbmNlLiIsIHlsYWI9IiIsCiAgICAgICAgIG1haW49IkluYXVndXJhbCBzcGVlY2hlcyIpCgojIHRoaXMgaXMgZm9yIG92ZXJhbGwgcGxhY2VzCmJlZXN3YXJtKHdvcmQuY291bnR+UGxhY2VzLAogICAgICAgICBkYXRhPXNlbnRlbmNlLmxpc3QucGxhY2UsCiAgICAgICAgIGhvcml6b250YWwgPSBUUlVFLCAKICAgICAgICAgcGNoPTE2LCAKICAgICAgICAgY29sPWFscGhhKGJyZXdlci5wYWwoOSwgIlNldDEiKSwgMC42KSwgCiAgICAgICAgIGNleD0wLjU1LCBjZXguYXhpcz0wLjgsIGNleC5sYWI9MC44LAogICAgICAgICBzcGFjaW5nPTUvbmxldmVscyhzZW50ZW5jZS5saXN0LnBsYWNlJEZpbGVPcmRlcmVkKSwKICAgICAgICAgbGFzPTIsIHhsYWI9Ik51bWJlciBvZiB3b3JkcyBpbiBhIHNlbnRlbmNlLiIsIHlsYWI9IiIsCiAgICAgICAgIG1haW49IkluYXVndXJhbCBzcGVlY2hlcyIpCgpgYGAKCgoKQW5kIHdlIHdhbnQgZXhwbG9yZSB0aGUgc2hvcnQgc2VudGVuY2VzIHByZXNpZGVudHMgdXN1YWxseSBzYXk6CmBgYHtyfQojcHJlc2lkZW50IGZyb20gU291dGgKc2VudGVuY2UubGlzdC5wbGFjZSU+JQogIGZpbHRlcihGaWxlPT0iR2VvcmdlV2FzaGluZ3RvbiIsd29yZC5jb3VudDw9MTApJT4lCiAgc2VsZWN0KHNlbnRlbmNlcykjJT4lc2FtcGxlX24oMTApCgoKc2VudGVuY2UubGlzdC5wbGFjZSU+JQogIGZpbHRlcihGaWxlPT0iSm9obkFkYW1zIiwgCiAgICAgICAgIHdvcmQuY291bnQ8PTEwKSU+JQogIHNlbGVjdChzZW50ZW5jZXMpCgpzZW50ZW5jZS5saXN0LnBsYWNlJT4lCiAgZmlsdGVyKEZpbGU9PSJBYnJhaGFtTGluY29sbiIsIAogICAgICAgICB3b3JkLmNvdW50PD0xMCklPiUKICBzZWxlY3Qoc2VudGVuY2VzKSMlPiVzYW1wbGVfbigxMCkKCgojCmZvbGRlci5wYXRoPSIuLi9kYXRhL2luYXVndXJhbHMvIgpmZi5hbGw8LUNvcnB1cyhEaXJTb3VyY2UoZm9sZGVyLnBhdGgpKQpmZi5hbGw8LXRtX21hcChmZi5hbGwsIHN0cmlwV2hpdGVzcGFjZSkKZmYuYWxsPC10bV9tYXAoZmYuYWxsLCBjb250ZW50X3RyYW5zZm9ybWVyKHRvbG93ZXIpKQpmZi5hbGw8LXRtX21hcChmZi5hbGwsIHJlbW92ZVdvcmRzLCBzdG9wd29yZHMoImVuZ2xpc2giKSkKZmYuYWxsPC10bV9tYXAoZmYuYWxsLCByZW1vdmVXb3JkcywgY2hhcmFjdGVyKDApKQpmZi5hbGw8LXRtX21hcChmZi5hbGwsIHJlbW92ZVB1bmN0dWF0aW9uKQp0ZG0uYWxsPC1UZXJtRG9jdW1lbnRNYXRyaXgoZmYuYWxsKQp0ZG0udGlkeT10aWR5KHRkbS5hbGwpCnRkbS5vdmVyYWxsPXN1bW1hcmlzZShncm91cF9ieSh0ZG0udGlkeSwgdGVybSksIHN1bShjb3VudCkpCndvcmRjbG91ZCh0ZG0ub3ZlcmFsbCR0ZXJtLCB0ZG0ub3ZlcmFsbCRgc3VtKGNvdW50KWAsCiAgICAgICAgICBzY2FsZT1jKDUsMC41KSwKICAgICAgICAgIG1heC53b3Jkcz0xMDAsCiAgICAgICAgICBtaW4uZnJlcT0xLAogICAgICAgICAgcmFuZG9tLm9yZGVyPUZBTFNFLAogICAgICAgICAgcm90LnBlcj0wLjMsCiAgICAgICAgICB1c2Uuci5sYXlvdXQ9VCwKICAgICAgICAgIHJhbmRvbS5jb2xvcj1GQUxTRSwKICAgICAgICAgICNjb2xvcnM9IkJMVUUiKSkKICAgICAgICAgIGNvbG9ycz1icmV3ZXIucGFsKDksIkJsdWVzIikpCgojIHRoZSAKZm9sZGVyLnBhdGgxPSIuLi9kYXRhL2luYXVndXJhbHMvYmVmb3Jld2FyLyIKZmYuYmVmb3Jld2FyPC1Db3JwdXMoRGlyU291cmNlKGZvbGRlci5wYXRoMSkpCmZmLmJlZm9yZXdhcjwtdG1fbWFwKGZmLmJlZm9yZXdhciwgc3RyaXBXaGl0ZXNwYWNlKQpmZi5iZWZvcmV3YXI8LXRtX21hcChmZi5iZWZvcmV3YXIsIGNvbnRlbnRfdHJhbnNmb3JtZXIodG9sb3dlcikpCmZmLmJlZm9yZXdhcjwtdG1fbWFwKGZmLmJlZm9yZXdhciwgcmVtb3ZlV29yZHMsIHN0b3B3b3JkcygiZW5nbGlzaCIpKQpmZi5iZWZvcmV3YXI8LXRtX21hcChmZi5iZWZvcmV3YXIsIHJlbW92ZVdvcmRzLCBjaGFyYWN0ZXIoMCkpCmZmLmJlZm9yZXdhcjwtdG1fbWFwKGZmLmJlZm9yZXdhciwgcmVtb3ZlUHVuY3R1YXRpb24pCnRkbS5hbGxiZWY8LVRlcm1Eb2N1bWVudE1hdHJpeChmZi5iZWZvcmV3YXIpCnRkbS50aWR5YmVmPXRpZHkodGRtLmFsbGJlZikKdGRtLm92ZXJhbGxiPXN1bW1hcmlzZShncm91cF9ieSh0ZG0udGlkeWJlZiwgdGVybSksIHN1bShjb3VudCkpCndvcmRjbG91ZCh0ZG0ub3ZlcmFsbGIkdGVybSwgdGRtLm92ZXJhbGxiJGBzdW0oY291bnQpYCwKICAgICAgICAgIHNjYWxlPWMoNSwwLjUpLAogICAgICAgICAgbWF4LndvcmRzPTEwMCwKICAgICAgICAgIG1pbi5mcmVxPTEsCiAgICAgICAgICByYW5kb20ub3JkZXI9RkFMU0UsCiAgICAgICAgICByb3QucGVyPTAuMywKICAgICAgICAgIHVzZS5yLmxheW91dD1ULAogICAgICAgICAgcmFuZG9tLmNvbG9yPUZBTFNFLAogICAgICAgICAgI2NvbG9ycz0iQkxVRSIpKQogICAgICAgICAgY29sb3JzPWJyZXdlci5wYWwoOSwiR3JlZW5zIikpCgpmb2xkZXIucGF0aG49Ii4uL2RhdGEvaW5hdWd1cmFscy9iZWZvcmV3YXIvbm9ydGgiCmZmLmFsbG48LUNvcnB1cyhEaXJTb3VyY2UoZm9sZGVyLnBhdGhuKSkKZmYuYWxsbjwtdG1fbWFwKGZmLmFsbG4sIHN0cmlwV2hpdGVzcGFjZSkKZmYuYWxsbjwtdG1fbWFwKGZmLmFsbG4sIGNvbnRlbnRfdHJhbnNmb3JtZXIodG9sb3dlcikpCmZmLmFsbG48LXRtX21hcChmZi5hbGxuLCByZW1vdmVXb3Jkcywgc3RvcHdvcmRzKCJlbmdsaXNoIikpCmZmLmFsbG48LXRtX21hcChmZi5hbGxuLCByZW1vdmVXb3JkcywgY2hhcmFjdGVyKDApKQpmZi5hbGxuPC10bV9tYXAoZmYuYWxsbiwgcmVtb3ZlUHVuY3R1YXRpb24pCnRkbS5hbGxuPC1UZXJtRG9jdW1lbnRNYXRyaXgoZmYuYWxsbikKdGRtLnRpZHluPXRpZHkodGRtLmFsbG4pCnRkbS5vdmVyYWxsbj1zdW1tYXJpc2UoZ3JvdXBfYnkodGRtLnRpZHluLCB0ZXJtKSwgc3VtKGNvdW50KSkKd29yZGNsb3VkKHRkbS5vdmVyYWxsbiR0ZXJtLHRkbS5vdmVyYWxsbiRgc3VtKGNvdW50KWAsCiAgICAgICAgICBzY2FsZT1jKDUsMC41KSwKICAgICAgICAgIG1heC53b3Jkcz0xMDAsCiAgICAgICAgICBtaW4uZnJlcT0xLAogICAgICAgICAgcmFuZG9tLm9yZGVyPUZBTFNFLAogICAgICAgICAgcm90LnBlcj0wLjMsCiAgICAgICAgICB1c2Uuci5sYXlvdXQ9VCwKICAgICAgICAgIHJhbmRvbS5jb2xvcj1GQUxTRSwKICAgICAgICAgICNjb2xvcnM9IkJMVUUiKSkKICAgICAgICAgIGNvbG9ycz1icmV3ZXIucGFsKDksIlJlZHMiKSkKCmZvbGRlci5wYXRocz0iLi4vZGF0YS9pbmF1Z3VyYWxzL2JlZm9yZXdhci9zb3V0aCIKZmYuYWxsczwtQ29ycHVzKERpclNvdXJjZShmb2xkZXIucGF0aHMpKQpmZi5hbGxzPC10bV9tYXAoZmYuYWxscywgc3RyaXBXaGl0ZXNwYWNlKQpmZi5hbGxzPC10bV9tYXAoZmYuYWxscywgY29udGVudF90cmFuc2Zvcm1lcih0b2xvd2VyKSkKZmYuYWxsczwtdG1fbWFwKGZmLmFsbHMsIHJlbW92ZVdvcmRzLCBzdG9wd29yZHMoImVuZ2xpc2giKSkKZmYuYWxsczwtdG1fbWFwKGZmLmFsbHMsIHJlbW92ZVdvcmRzLCBjaGFyYWN0ZXIoMCkpCmZmLmFsbHM8LXRtX21hcChmZi5hbGxzLCByZW1vdmVQdW5jdHVhdGlvbikKdGRtLmFsbHM8LVRlcm1Eb2N1bWVudE1hdHJpeChmZi5hbGxzKQp0ZG0udGlkeXM9dGlkeSh0ZG0uYWxscykKdGRtLm92ZXJhbGxzPXN1bW1hcmlzZShncm91cF9ieSh0ZG0udGlkeXMsIHRlcm0pLCBzdW0oY291bnQpKQp3b3JkY2xvdWQodGRtLm92ZXJhbGxzJHRlcm0sIHRkbS5vdmVyYWxscyRgc3VtKGNvdW50KWAsCiAgICAgICAgICBzY2FsZT1jKDUsMC41KSwKICAgICAgICAgIG1heC53b3Jkcz0xMDAsCiAgICAgICAgICBtaW4uZnJlcT0xLAogICAgICAgICAgcmFuZG9tLm9yZGVyPUZBTFNFLAogICAgICAgICAgcm90LnBlcj0wLjMsCiAgICAgICAgICB1c2Uuci5sYXlvdXQ9VCwKICAgICAgICAgIHJhbmRvbS5jb2xvcj1GQUxTRSwKICAgICAgICAgICNjb2xvcnM9IkJMVUUiKSkKICAgICAgICAgIGNvbG9ycz1icmV3ZXIucGFsKDksIkJsdWVzIikpCmBgYAoKCgoKI0RhdGEgYW5hbHlzaXMgCgpTZW50ZW5jZSBsZW5ndGggdmFyaWF0aW9uIG92ZXIgdGhlIGNvdXJzZSBvZiB0aGUgc3BlZWNoLCB3aXRoIGVtb3Rpb25zLiAKCkhvdyBvdXIgcHJlc2lkZW50cyAob3IgY2FuZGlkYXRlcykgYWx0ZXJuYXRlIGJldHdlZW4gbG9uZyBhbmQgc2hvcnQgc2VudGVuY2VzIGFuZCBob3cgdGhleSBzaGlmdCBiZXR3ZWVuIGRpZmZlcmVudCBzZW50aW1lbnRzIGluIHRoZWlyIHNwZWVjaGVzLiBJdCBpcyBpbnRlcmVzdGluZyB0byBub3RlIHRoYXQgc29tZSBwcmVzaWRlbnRpYWwgY2FuZGlkYXRlcycgc3BlZWNoIGFyZSBtb3JlIGNvbG9yZnVsIHRoYW4gb3RoZXJzLiAKCgpgYGB7ciwgZmlnLmhlaWdodD0yLjUsIGZpZy53aWR0aD0yfQpwYXIobWZyb3c9Yyg0LDEpLCBtYXI9YygxLDAsMiwwKSwgYnR5PSJuIiwgeGF4dD0ibiIsIHlheHQ9Im4iLCBmb250Lm1haW49MSkKCmYucGxvdHNlbnQubGVuKEluLmxpc3Q9c2VudGVuY2UubGlzdCwgSW5GaWxlPSJHZW9yZ2VXYXNoaW5ndG9uIiwgCkluVHlwZT0iaW5hdWciLCBJblRlcm09MSwgUHJlc2lkZW50PSJHZW9yZ2UgV2FzaGluZ3RvbiIpCgpmLnBsb3RzZW50LmxlbihJbi5saXN0PXNlbnRlbmNlLmxpc3QsIEluRmlsZT0iVGhvbWFzSmVmZmVyc29uIiwgCkluVHlwZT0iaW5hdWciLCBJblRlcm09MSwgUHJlc2lkZW50PSJUaG9tYXMgSmVmZmVyc29uIikKCmYucGxvdHNlbnQubGVuKEluLmxpc3Q9c2VudGVuY2UubGlzdCwgSW5GaWxlPSJBYnJhaGFtTGluY29sbiIsIApJblR5cGU9ImluYXVnIiwgSW5UZXJtPTEsIFByZXNpZGVudD0iQWJyYWhhbSBMaW5jb2xuIikKCmYucGxvdHNlbnQubGVuKEluLmxpc3Q9c2VudGVuY2UubGlzdCwgSW5GaWxlPSJSdXRoZXJmb3JkQkhheWVzIiwgCkluVHlwZT0iaW5hdWciLCBJblRlcm09MSwgUHJlc2lkZW50PSJSdXRoZXJmb3JkIEIuIEhheWVzIikKYGBgCgojVGhlbiBJIGFtIGdvaW5nIHRvIGZpbmQgc29tZSBzZW50ZW5jZXMgdGhhdCBjYW4gaGF2ZSBhIGdvb2QgcmVwcmVzZW50IG9mIHRoZSBwcmVzaWRlbnQncyBjaGFyYWN0ZXJpc3RpYwoKYGBge3J9CmNhdCgiXG5HZW9yZ2UgV2FzaGluZ3RvXG4iKQpzcGVlY2guZGY9dGJsX2RmKHNlbnRlbmNlLmxpc3QucGxhY2UpJT4lCmZpbHRlcihGaWxlPT0iR2VvcmdlV2FzaGluZ3RvbiIsIHR5cGU9PSJpbmF1ZyIsIHdvcmQuY291bnQ+PTQpJT4lCnNlbGVjdChzZW50ZW5jZXMsIGFuZ2VyOnRydXN0KQpzcGVlY2guZGY9YXMuZGF0YS5mcmFtZShzcGVlY2guZGYpCmFzLmNoYXJhY3RlcihzcGVlY2guZGYkc2VudGVuY2VzW2FwcGx5KHNwZWVjaC5kZlssLTFdLCAyLCB3aGljaC5tYXgpXSkKCmNhdCgiXG5UaG9tYXMgSmVmZmVyc29uXG4iKQpzcGVlY2guZGY9dGJsX2RmKHNlbnRlbmNlLmxpc3QucGxhY2UpJT4lCmZpbHRlcihGaWxlPT0iVGhvbWFzSmVmZmVyc29uIiwgdHlwZT09ImluYXVnIiwgVGVybT09MSwgd29yZC5jb3VudD49NSklPiUKc2VsZWN0KHNlbnRlbmNlcywgYW5nZXI6dHJ1c3QpCnNwZWVjaC5kZj1hcy5kYXRhLmZyYW1lKHNwZWVjaC5kZikKYXMuY2hhcmFjdGVyKHNwZWVjaC5kZiRzZW50ZW5jZXNbYXBwbHkoc3BlZWNoLmRmWywtMV0sIDIsIHdoaWNoLm1heCldKQoKY2F0KCJcbkFicmFoYW0gTGluY29sblxuIikKc3BlZWNoLmRmPXRibF9kZihzZW50ZW5jZS5saXN0LnBsYWNlKSU+JQpmaWx0ZXIoRmlsZT09IkFicmFoYW1MaW5jb2xuIiwgdHlwZT09ImluYXVnIiwgVGVybT09MSwgd29yZC5jb3VudD49NCklPiUKc2VsZWN0KHNlbnRlbmNlcywgYW5nZXI6dHJ1c3QpCnNwZWVjaC5kZj1hcy5kYXRhLmZyYW1lKHNwZWVjaC5kZikKYXMuY2hhcmFjdGVyKHNwZWVjaC5kZiRzZW50ZW5jZXNbYXBwbHkoc3BlZWNoLmRmWywtMV0sIDIsIHdoaWNoLm1heCldKQoKY2F0KCJcblJ1dGhlcmZvcmQgQi4gSGF5ZXNcbiIpCnNwZWVjaC5kZj10YmxfZGYoc2VudGVuY2UubGlzdC5wbGFjZSklPiUKZmlsdGVyKEZpbGU9PSJSdXRoZXJmb3JkQkhheWVzIiwgdHlwZT09ImluYXVnIiwgVGVybT09MSwgd29yZC5jb3VudD49NSklPiUKc2VsZWN0KHNlbnRlbmNlcywgYW5nZXI6dHJ1c3QpCnNwZWVjaC5kZj1hcy5kYXRhLmZyYW1lKHNwZWVjaC5kZikKYXMuY2hhcmFjdGVyKHNwZWVjaC5kZiRzZW50ZW5jZXNbYXBwbHkoc3BlZWNoLmRmWywtMV0sIDIsIHdoaWNoLm1heCldKQoKYGBgCgoKIyBDbHVzdGVyaW5nIG9mIGVtb3Rpb25zCmBgYHtyLCBmaWcud2lkdGg9MiwgZmlnLmhlaWdodD0yfQpoZWF0bWFwLjIoY29yKHNlbnRlbmNlLmxpc3QlPiVmaWx0ZXIodHlwZT09ImluYXVnIiklPiVzZWxlY3QoYW5nZXI6dHJ1c3QpKSwgCnNjYWxlID0gIm5vbmUiLCAKY29sID0gYmx1ZXJlZCgxMDApLCAsIG1hcmdpbj1jKDYsIDYpLCBrZXk9RiwKdHJhY2UgPSAibm9uZSIsIGRlbnNpdHkuaW5mbyA9ICJub25lIikKCnBhcihtYXI9Yyg0LCA2LCAyLCAxKSkKZW1vLm1lYW5zLm5vcnRoPWNvbE1lYW5zKHNlbGVjdChzZW50ZW5jZS5saXN0LnBsYWNlJT4lZmlsdGVyKFBsYWNlcz09Ik4iKSwgYW5nZXI6dHJ1c3QpPjAuMDEpCmVtby5tZWFucy5zb3V0aD1jb2xNZWFucyhzZWxlY3Qoc2VudGVuY2UubGlzdC5wbGFjZSU+JWZpbHRlcihQbGFjZXM9PSJTIiksIGFuZ2VyOnRydXN0KT4wLjAxKQpjb2wudXNlPWMoInJlZDIiLCAiZGFya2dvbGRlbnJvZDEiLCAKImNoYXJ0cmV1c2UzIiwgImJsdWV2aW9sZXQiLAoiZGFya2dvbGRlbnJvZDIiLCAiZG9kZ2VyYmx1ZTMiLCAKImRhcmtnb2xkZW5yb2QxIiwgImRhcmtnb2xkZW5yb2QxIikKcGFyKG1mcm93PWMoMSwyKSkKYmFycGxvdChlbW8ubWVhbnMubm9ydGhbb3JkZXIoZW1vLm1lYW5zLm5vcnRoKV0sIGxhcz0yLCBjb2w9Y29sLnVzZVtvcmRlcihlbW8ubWVhbnMubm9ydGgpXSwgaG9yaXo9VCwgbWFpbj0iTm9ydGggbGlrZWx5IikKYmFycGxvdChlbW8ubWVhbnMuc291dGhbb3JkZXIoZW1vLm1lYW5zLnNvdXRoKV0sIGxhcz0yLCBjb2w9Y29sLnVzZVtvcmRlcihlbW8ubWVhbnMuc291dGgpXSwgaG9yaXo9VCwgbWFpbj0iU291dGggbGlrZWx5IikKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD0zLjMsIGZpZy53aWR0aD0zLjd9CnByZXNpZC5zdW1tYXJ5PXRibF9kZihzZW50ZW5jZS5saXN0LnBsYWNlKSU+JQpmaWx0ZXIodHlwZT09ImluYXVnIiwpJT4lCiNncm91cF9ieShwYXN0ZTAodHlwZSwgRmlsZSkpJT4lCmdyb3VwX2J5KEZpbGVkaXJlY3Rpb24pJT4lCnN1bW1hcmlzZSgKYW5nZXI9bWVhbihhbmdlciksCmFudGljaXBhdGlvbj1tZWFuKGFudGljaXBhdGlvbiksCmRpc2d1c3Q9bWVhbihkaXNndXN0KSwKZmVhcj1tZWFuKGZlYXIpLApqb3k9bWVhbihqb3kpLApzYWRuZXNzPW1lYW4oc2FkbmVzcyksCnN1cnByaXNlPW1lYW4oc3VycHJpc2UpLAp0cnVzdD1tZWFuKHRydXN0KQojbmVnYXRpdmU9bWVhbihuZWdhdGl2ZSksCiNwb3NpdGl2ZT1tZWFuKHBvc2l0aXZlKQopCgpwcmVzaWQuc3VtbWFyeT1hcy5kYXRhLmZyYW1lKHByZXNpZC5zdW1tYXJ5KQpyb3duYW1lcyhwcmVzaWQuc3VtbWFyeSk9YXMuY2hhcmFjdGVyKChwcmVzaWQuc3VtbWFyeVssMV0pKQprbS5yZXM9a21lYW5zKHByZXNpZC5zdW1tYXJ5WywtMV0sIGl0ZXIubWF4PTIwMCwKNSkKZnZpel9jbHVzdGVyKGttLnJlcywgCnN0YW5kPUYsIHJlcGVsPSBUUlVFLApkYXRhID0gcHJlc2lkLnN1bW1hcnlbLC0xXSwgeGxhYj0iIiwgeGF4dD0ibiIsCnNob3cuY2x1c3QuY2VudD1GQUxTRSkKYGBgCgojTERBIERhdGEgYW5hbHlzaXMgCgpGb3IgdG9waWMgbW9kZWxpbmcsIHdlIHByZXBhcmUgYSBjb3JwdXMgb2Ygc2VudGVuY2Ugc25pcGV0cyBhcyBmb2xsb3dzLiBGb3IgZWFjaCBzcGVlY2gsIHdlIHN0YXJ0IHdpdGggc2VudGVuY2VzIGFuZCBwcmVwYXJlIGEgc25pcGV0IHdpdGggYSBnaXZlbiBzZW50ZW5jZSB3aXRoIHRoZSBmbGFua2luZyBzZW50ZW5jZXMuIAoKYGBge3J9CnNlbnRlbmNlLmxpc3Q8LXNlbnRlbmNlLmxpc3QucGxhY2UKY29ycHVzLmxpc3Q9c2VudGVuY2UubGlzdFsyOihucm93KHNlbnRlbmNlLmxpc3QpLTEpLCBdCnNlbnRlbmNlLnByZT1zZW50ZW5jZS5saXN0JHNlbnRlbmNlc1sxOihucm93KHNlbnRlbmNlLmxpc3QpLTIpXQpzZW50ZW5jZS5wb3N0PXNlbnRlbmNlLmxpc3Qkc2VudGVuY2VzWzM6KG5yb3coc2VudGVuY2UubGlzdCktMSldCmNvcnB1cy5saXN0JHNuaXBldHM9cGFzdGUoc2VudGVuY2UucHJlLCBjb3JwdXMubGlzdCRzZW50ZW5jZXMsIHNlbnRlbmNlLnBvc3QsIHNlcD0iICIpCnJtLnJvd3M9KDE6bnJvdyhjb3JwdXMubGlzdCkpW2NvcnB1cy5saXN0JHNlbnQuaWQ9PTFdCnJtLnJvd3M9YyhybS5yb3dzLCBybS5yb3dzLTEpCmNvcnB1cy5saXN0PWNvcnB1cy5saXN0Wy1ybS5yb3dzLCBdCmBgYAoKIyMgVGV4dCBtaW5pbmcKYGBge3J9CmRvY3MgPC0gQ29ycHVzKFZlY3RvclNvdXJjZShjb3JwdXMubGlzdCRzbmlwZXRzKSkKd3JpdGVMaW5lcyhhcy5jaGFyYWN0ZXIoZG9jc1tbc2FtcGxlKDE6bnJvdyhjb3JwdXMubGlzdCksIDEpXV0pKQpgYGAKCgoKYGBge3J9CiNyZW1vdmUgcG90ZW50aWFsbHkgcHJvYmxlbWF0aWMgc3ltYm9scwpkb2NzIDwtdG1fbWFwKGRvY3MsY29udGVudF90cmFuc2Zvcm1lcih0b2xvd2VyKSkKd3JpdGVMaW5lcyhhcy5jaGFyYWN0ZXIoZG9jc1tbc2FtcGxlKDE6bnJvdyhjb3JwdXMubGlzdCksIDEpXV0pKQoKI3JlbW92ZSBwdW5jdHVhdGlvbgpkb2NzIDwtIHRtX21hcChkb2NzLCByZW1vdmVQdW5jdHVhdGlvbikKd3JpdGVMaW5lcyhhcy5jaGFyYWN0ZXIoZG9jc1tbc2FtcGxlKDE6bnJvdyhjb3JwdXMubGlzdCksIDEpXV0pKQoKI1N0cmlwIGRpZ2l0cwpkb2NzIDwtIHRtX21hcChkb2NzLCByZW1vdmVOdW1iZXJzKQp3cml0ZUxpbmVzKGFzLmNoYXJhY3Rlcihkb2NzW1tzYW1wbGUoMTpucm93KGNvcnB1cy5saXN0KSwgMSldXSkpCgojcmVtb3ZlIHN0b3B3b3Jkcwpkb2NzIDwtIHRtX21hcChkb2NzLCByZW1vdmVXb3Jkcywgc3RvcHdvcmRzKCJlbmdsaXNoIikpCndyaXRlTGluZXMoYXMuY2hhcmFjdGVyKGRvY3NbW3NhbXBsZSgxOm5yb3coY29ycHVzLmxpc3QpLCAxKV1dKSkKCiNyZW1vdmUgd2hpdGVzcGFjZQpkb2NzIDwtIHRtX21hcChkb2NzLCBzdHJpcFdoaXRlc3BhY2UpCndyaXRlTGluZXMoYXMuY2hhcmFjdGVyKGRvY3NbW3NhbXBsZSgxOm5yb3coY29ycHVzLmxpc3QpLCAxKV1dKSkKCiNTdGVtIGRvY3VtZW50CmRvY3MgPC0gdG1fbWFwKGRvY3Msc3RlbURvY3VtZW50KQp3cml0ZUxpbmVzKGFzLmNoYXJhY3Rlcihkb2NzW1tzYW1wbGUoMTpucm93KGNvcnB1cy5saXN0KSwgMSldXSkpCmBgYAoKI1RvcGljIG1vZGVsaW5nCgpHZW5nZXJhdGUgZG9jdW1lbnQtdGVybSBtYXRyaWNlcy4gCgpgYGB7cn0KZHRtIDwtIERvY3VtZW50VGVybU1hdHJpeChkb2NzKQojY29udmVydCByb3duYW1lcyB0byBmaWxlbmFtZXMjY29udmVydCByb3duYW1lcyB0byBmaWxlbmFtZXMKcm93bmFtZXMoZHRtKSA8LSBwYXN0ZShjb3JwdXMubGlzdCR0eXBlLCBjb3JwdXMubGlzdCRGaWxlLApjb3JwdXMubGlzdCRUZXJtLCBjb3JwdXMubGlzdCRzZW50LmlkLCBzZXA9Il8iKQoKcm93VG90YWxzIDwtIGFwcGx5KGR0bSAsIDEsIHN1bSkgI0ZpbmQgdGhlIHN1bSBvZiB3b3JkcyBpbiBlYWNoIERvY3VtZW50CgpkdG0gIDwtIGR0bVtyb3dUb3RhbHM+IDAsIF0KY29ycHVzLmxpc3Q9Y29ycHVzLmxpc3Rbcm93VG90YWxzPjAsIF0KCmBgYAoKUnVuIExEQQoKYGBge3J9CiNTZXQgcGFyYW1ldGVycyBmb3IgR2liYnMgc2FtcGxpbmcKYnVybmluIDwtIDQwMDAKaXRlciA8LSAyMDAwCnRoaW4gPC0gNTAwCnNlZWQgPC1saXN0KDIwMDMsNSw2MywxMDAwMDEsNzY1KQpuc3RhcnQgPC0gNQpiZXN0IDwtIFRSVUUKCiNOdW1iZXIgb2YgdG9waWNzCmsgPC0gMTUKCiNSdW4gTERBIHVzaW5nIEdpYmJzIHNhbXBsaW5nCmxkYU91dCA8LUxEQShkdG0sIGssIG1ldGhvZD0iR2liYnMiLCBjb250cm9sPWxpc3QobnN0YXJ0PW5zdGFydCwgc2VlZCA9IHNlZWQsIGJlc3Q9YmVzdCxidXJuaW4gPSBidXJuaW4sIGl0ZXIgPSBpdGVyLCB0aGluPXRoaW4pKQojd3JpdGUgb3V0IHJlc3VsdHMKI2RvY3MgdG8gdG9waWNzCmxkYU91dC50b3BpY3MgPC0gYXMubWF0cml4KHRvcGljcyhsZGFPdXQpKQp0YWJsZShjKDE6aywgbGRhT3V0LnRvcGljcykpCndyaXRlLmNzdihsZGFPdXQudG9waWNzLAogICAgICAgICAgZmlsZT1wYXN0ZSgiLi4vb3V0L0xEQUdpYmJzIixrLCJEb2NzVG9Ub3BpY3MuY3N2IikpCgojdG9wIDYgdGVybXMgaW4gZWFjaCB0b3BpYwpsZGFPdXQudGVybXMgPC0gYXMubWF0cml4KHRlcm1zKGxkYU91dCwyMCkpCndyaXRlLmNzdihsZGFPdXQudGVybXMsCiAgICAgICAgICBmaWxlPXBhc3RlKCIuLi9vdXQvTERBR2liYnMiLGssIlRvcGljc1RvVGVybXMuY3N2IikpCgojcHJvYmFiaWxpdGllcyBhc3NvY2lhdGVkIHdpdGggZWFjaCB0b3BpYyBhc3NpZ25tZW50CnRvcGljUHJvYmFiaWxpdGllcyA8LSBhcy5kYXRhLmZyYW1lKGxkYU91dEBnYW1tYSkKd3JpdGUuY3N2KHRvcGljUHJvYmFiaWxpdGllcyxmaWxlPXBhc3RlKCIvVXNlcnMvd2VzdHNwcmluZ2FtZXJpY2EvRG93bmxvYWRzL3drMi1UZXh0TWluaW5nL291dC9MREFHaWJicyIsaywiVG9waWNQcm9iYWJpbGl0aWVzLmNzdiIpKQpgYGAKCmBgYHtyfQp0ZXJtcy5iZXRhPWxkYU91dEBiZXRhCnRlcm1zLmJldGE9c2NhbGUodGVybXMuYmV0YSkKdG9waWNzLnRlcm1zPU5VTEwKZm9yKGkgaW4gMTprKXsKdG9waWNzLnRlcm1zPXJiaW5kKHRvcGljcy50ZXJtcywgbGRhT3V0QHRlcm1zW29yZGVyKHRlcm1zLmJldGFbaSxdLCBkZWNyZWFzaW5nID0gVFJVRSlbMTo3XV0pCn0KdG9waWNzLnRlcm1zCmxkYU91dC50ZXJtcwpgYGAKCkJhc2VkIG9uIHRoZSBtb3N0IHBvcHVsYXIgdGVybXMgYW5kIHRoZSBtb3N0IHNhbGllbnQgdGVybXMgZm9yIGVhY2ggdG9waWMsIHdlIGFzc2lnbiBhIGhhc2h0YWcgdG8gZWFjaCB0b3BpYy4gVGhpcyBwYXJ0IHJlcXVpcmUgbWFudWFsIHNldHVwIGFzIHRoZSB0b3BpY3MgYXJlIGxpa2VseSB0byBjaGFuZ2UuIAoKYGBge3J9Cgp0b3BpY3Mub2xkaGFzaD1jKCJFY29ub215IiwgIkFtZXJpY2EiLCAiRGVmZW5zZSIsICJCZWxpZWYiLCAiRWxlY3Rpb24iLCAiUGF0cmlvdGlzbSIsICJVbml0eSIsICJHb3Zlcm5tZW50IiwgIlJlZm9ybSIsICJUZW1wb3JhbCIsICJXb3JraW5nRmFtaWxpZXMiLCAiRnJlZWRvbSIsICJFcXVhbGl0eSIsICJNaXNjIiwgIkxlZ2lzbGF0aW9uIikKCnRvcGljc25ldy5oYXNoPWMoImV2ZXJpIiwgIndhciIgLCJsYXciLCAgInVwb24iLCJuYXRpb24iLCAidW5pb24iLCAiY29uc3RpdHV0Iiwid2lsbCIsInB1YmxpYyIsImludGVyZXN0Iiwic3RhdGUiLCAgICAgImdyZWF0IiwiZHV0aSIsICJwZW9wbCIsInJpZ2h0IikKdG9waWNzLmhhc2g9dG9waWNzbmV3Lmhhc2gKY29ycHVzLmxpc3QkbGRhdG9waWM9YXMudmVjdG9yKGxkYU91dC50b3BpY3MpCmNvcnB1cy5saXN0JGxkYWhhc2g9dG9waWNzLmhhc2hbbGRhT3V0LnRvcGljc10KCmNvbG5hbWVzKHRvcGljUHJvYmFiaWxpdGllcyk9dG9waWNzLmhhc2gKY29ycHVzLmxpc3QuZGY9Y2JpbmQoY29ycHVzLmxpc3QsIHRvcGljUHJvYmFiaWxpdGllcykKYGBgCgojIENsdXN0ZXJpbmcgb2YgdG9waWNzCmBgYHtyLCBmaWcud2lkdGg9MywgZmlnLmhlaWdodD00fQpwYXIobWFyPWMoMSwxLDEsMSkpCnRvcGljLnN1bW1hcnk9dGJsX2RmKGNvcnB1cy5saXN0LmRmKSU+JQpmaWx0ZXIodHlwZSVpbiVjKCJpbmF1ZyIpKSU+JQpzZWxlY3QoRmlsZWRpcmVjdGlvbiwgZXZlcmk6IHJpZ2h0KSU+JQpncm91cF9ieShGaWxlZGlyZWN0aW9uKSU+JQpzdW1tYXJpc2VfZWFjaChmdW5zKG1lYW4pKQp0b3BpYy5zdW1tYXJ5PWFzLmRhdGEuZnJhbWUodG9waWMuc3VtbWFyeSkKcm93bmFtZXModG9waWMuc3VtbWFyeSk9dG9waWMuc3VtbWFyeVssMV0KCgp0b3BpYy5wbG90PWMoMToxNSkKcHJpbnQodG9waWNzLmhhc2hbdG9waWMucGxvdF0pCgpoZWF0bWFwLjIoYXMubWF0cml4KHRvcGljLnN1bW1hcnlbLHRvcGljLnBsb3QrMV0pLCAKc2NhbGUgPSAiY29sdW1uIiwga2V5PUYsIApjb2wgPSBibHVlcmVkKDEwMCksCmNleFJvdyA9IDAuOCwgY2V4Q29sID0gMC45LCBtYXJnaW5zID0gYyg4LCA4KSwKdHJhY2UgPSAibm9uZSIsIGRlbnNpdHkuaW5mbyA9ICJub25lIikKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTMuMywgZmlnLmhlaWdodD01fQogICAgCgoKcGFyKG1mcm93PWMoNSwgMSksIG1hcj1jKDEsMSwyLDApLCBidHk9Im4iLCB4YXh0PSJuIiwgeWF4dD0ibiIpCgp0b3BpYy5wbG90PWMoMSwgMTMsIDE0LCAxNSwgOCwgOSwgMTIpCnByaW50KHRvcGljcy5oYXNoW3RvcGljLnBsb3RdKQoKc3BlZWNoLmRmPXRibF9kZihjb3JwdXMubGlzdC5kZiklPiVmaWx0ZXIoRmlsZT09Ikdlb3JnZVdhc2hpbmd0b24iLCB0eXBlPT0iaW5hdWciLFRlcm09PTEpJT4lc2VsZWN0KHNlbnQuaWQsIGV2ZXJpOiByaWdodCkKc3BlZWNoLmRmPWFzLm1hdHJpeChzcGVlY2guZGYpCnNwZWVjaC5kZlssLTFdPXJlcGxhY2Uoc3BlZWNoLmRmWywtMV0sIHNwZWVjaC5kZlssLTFdPDEvMTUsIDAuMDAxKQpzcGVlY2guZGZbLC0xXT1mLnNtb290aC50b3BpYyh4PXNwZWVjaC5kZlssMV0sIHk9c3BlZWNoLmRmWywtMV0pCnBsb3Quc3RhY2tlZChzcGVlY2guZGZbLDFdLCBzcGVlY2guZGZbLHRvcGljLnBsb3QrMV0sIAp4bGFiPSJTZW50ZW5jZXMiLCB5bGFiPSJUb3BpYyBzaGFyZSIsIG1haW49Ikdlb3JnZVdhc2hpbmd0b24iKQoKc3BlZWNoLmRmPXRibF9kZihjb3JwdXMubGlzdC5kZiklPiVmaWx0ZXIoRmlsZT09IlRob21hc0plZmZlcnNvbiIsIHR5cGU9PSJpbmF1ZyIsIFRlcm09PTEpJT4lc2VsZWN0KHNlbnQuaWQsIGV2ZXJpOiByaWdodCkKc3BlZWNoLmRmPWFzLm1hdHJpeChzcGVlY2guZGYpCnNwZWVjaC5kZlssLTFdPXJlcGxhY2Uoc3BlZWNoLmRmWywtMV0sIHNwZWVjaC5kZlssLTFdPDEvMTUsIDAuMDAxKQpzcGVlY2guZGZbLC0xXT1mLnNtb290aC50b3BpYyh4PXNwZWVjaC5kZlssMV0sIHk9c3BlZWNoLmRmWywtMV0pCnBsb3Quc3RhY2tlZChzcGVlY2guZGZbLDFdLCBzcGVlY2guZGZbLHRvcGljLnBsb3QrMV0sCnhsYWI9IlNlbnRlbmNlcyIsIHlsYWI9IlRvcGljIHNoYXJlIiwgbWFpbj0iVGhvbWFzSmVmZmVyc29uIikKCnNwZWVjaC5kZj10YmxfZGYoY29ycHVzLmxpc3QuZGYpJT4lZmlsdGVyKEZpbGU9PSJVbHlzc2VzU0dyYW50IiwgdHlwZT09ImluYXVnIiwgVGVybT09MSklPiVzZWxlY3Qoc2VudC5pZCwgZXZlcmk6IHJpZ2h0KQpzcGVlY2guZGY9YXMubWF0cml4KHNwZWVjaC5kZikKc3BlZWNoLmRmWywtMV09cmVwbGFjZShzcGVlY2guZGZbLC0xXSwgc3BlZWNoLmRmWywtMV08MS8xNSwgMC4wMDEpCnNwZWVjaC5kZlssLTFdPWYuc21vb3RoLnRvcGljKHg9c3BlZWNoLmRmWywxXSwgeT1zcGVlY2guZGZbLC0xXSkKcGxvdC5zdGFja2VkKHNwZWVjaC5kZlssMV0sIHNwZWVjaC5kZlssdG9waWMucGxvdCsxXSwgCnhsYWI9IlNlbnRlbmNlcyIsIHlsYWI9IlRvcGljIHNoYXJlIiwgbWFpbj0iVWx5c3Nlc1NHcmFudCIpCgpzcGVlY2guZGY9dGJsX2RmKGNvcnB1cy5saXN0LmRmKSU+JWZpbHRlcihGaWxlPT0iQWJyYWhhbUxpbmNvbG4iLCB0eXBlPT0iaW5hdWciLCBUZXJtPT0xKSU+JXNlbGVjdChzZW50LmlkLCBldmVyaTogcmlnaHQpCnNwZWVjaC5kZj1hcy5tYXRyaXgoc3BlZWNoLmRmKQpzcGVlY2guZGZbLC0xXT1yZXBsYWNlKHNwZWVjaC5kZlssLTFdLCBzcGVlY2guZGZbLC0xXTwxLzE1LCAwLjAwMSkKc3BlZWNoLmRmWywtMV09Zi5zbW9vdGgudG9waWMoeD1zcGVlY2guZGZbLDFdLCB5PXNwZWVjaC5kZlssLTFdKQpwbG90LnN0YWNrZWQoc3BlZWNoLmRmWywxXSwgc3BlZWNoLmRmWyx0b3BpYy5wbG90KzFdLAp4bGFiPSJTZW50ZW5jZXMiLCB5bGFiPSJUb3BpYyBzaGFyZSIsIG1haW49IkFicmFoYW1MaW5jb2xuIikKCnNwZWVjaC5kZj10YmxfZGYoY29ycHVzLmxpc3QuZGYpJT4lZmlsdGVyKEZpbGU9PSJKYW1lc01vbnJvZSIsIHR5cGU9PSJpbmF1ZyIsVGVybT09MSklPiVzZWxlY3Qoc2VudC5pZCwgZXZlcmk6IHJpZ2h0KQpzcGVlY2guZGY9YXMubWF0cml4KHNwZWVjaC5kZikKc3BlZWNoLmRmWywtMV09cmVwbGFjZShzcGVlY2guZGZbLC0xXSwgc3BlZWNoLmRmWywtMV08MS8xNSwgMC4wMDEpCnNwZWVjaC5kZlssLTFdPWYuc21vb3RoLnRvcGljKHg9c3BlZWNoLmRmWywxXSwgeT1zcGVlY2guZGZbLC0xXSkKcGxvdC5zdGFja2VkKHNwZWVjaC5kZlssMV0sIHNwZWVjaC5kZlssdG9waWMucGxvdCsxXSwKeGxhYj0iU2VudGVuY2VzIiwgeWxhYj0iVG9waWMgc2hhcmUiLCBtYWluPSJKYW1lc01vbnJvZSIpCgpgYGAKCgpgYGB7ciwgZmlnLndpZHRoPTMsIGZpZy5oZWlnaHQ9M30KcHJlc2lkLnN1bW1hcnk9dGJsX2RmKGNvcnB1cy5saXN0LmRmKSU+JQpmaWx0ZXIodHlwZT09ImluYXVnIiklPiUKc2VsZWN0KEZpbGVkaXJlY3Rpb24sIGV2ZXJpOiByaWdodCklPiUKZ3JvdXBfYnkoRmlsZWRpcmVjdGlvbiklPiUKc3VtbWFyaXNlX2VhY2goZnVucyhtZWFuKSkKCnByZXNpZC5zdW1tYXJ5PWFzLmRhdGEuZnJhbWUocHJlc2lkLnN1bW1hcnkpCnJvd25hbWVzKHByZXNpZC5zdW1tYXJ5KT1hcy5jaGFyYWN0ZXIoKHByZXNpZC5zdW1tYXJ5WywxXSkpCmttLnJlcz1rbWVhbnMoc2NhbGUocHJlc2lkLnN1bW1hcnlbLC0xXSksIGl0ZXIubWF4PTIwMCwKNSkKZnZpel9jbHVzdGVyKGttLnJlcywgCnN0YW5kPVQsIHJlcGVsPSBUUlVFLApkYXRhID0gcHJlc2lkLnN1bW1hcnlbLC0xXSwKc2hvdy5jbHVzdC5jZW50PUZBTFNFKQpgYGAKIyNDb25jbHVzaW9uczoKI0FjY29yZGluZyB0byB0aGUgYW5hbHlzaXMsIHdlIGZpbmQgdGhhdAogV2hlbiBpdCBjb21lcyB0byBudW1iZXIgb2Ygd29yZHMgaW4gcHJlc2lkZW50cydhdWd1cmFsIHByZXNlbnRhdGlvbiwgdGhlIHNvdXRoIGlzIG5vdCBzdGF0aXN0aWNhbGx5IGRpZmZlcmVudCBmcm9tIHRoZSBub3J0aCwgd2hpbGUgdGhleSBkbyBzcGVhayBhIGxpdHRsZSBzaG9ydGVyIG9uIGF2ZXJhZ2UuCgoKIEFsbCBwcmVzaWRlbnRzIGxpa2UgdG8gdXNlIHRoZSB3b3JkICJXSWxsIixtYXliZSB0aGV5IGFyZSBwcm9taXNpbmcgdGhlIGF1ZGllbmNlIHdpdGggYSBnb29kIGZ1dHVyZSBvciB0aGV5IHdvdWxkIGxpa2UgdG8gc2hvdyBoaXMgc3Ryb25nIHdpbGxpbmduZXNzLiBJbiBlYXJseSBwZXJpb2QgIlBlb3BsZSIgYW5kICJHb3Zlcm5tZW50IiBoYXMgbW9yZSBjaGFuY2UgdG8gYXBwZWFyIGluIHRoZSBwcmVzZW50YXRpb24gdGhhbiBub3dhZGF5cy4gUHJlc2lkZW50cyBmcm9tIG5vcnRoIGxpa2UgdG8gc2F5IGFib3V0ICJQZW9wbGUiLCB3aGlsZSAiU291dGgiIGlzIG1vcmUgbGlrZWx5IHRvIHRhbGsgYWJvdXQgU3RhdGVzLiBUaGlzIHJlYWxseSBtYWtlIHNlbnNlIHRoYXQgU291dGhlcm5lcnMgd2FudCBhIG1vcmUgdW5pdGVkIFN0YXRlcyBpbnN0ZWFkIG9mIGEgVW5pdGVkIFN0YXRlcyB3aXRoIGEgc3Ryb25nIGdvdmVybm1lbnQuIEFuZCB0aGUgbm9ydGggcGVvcGxlIHVyZ2UgdGhlbSB0byBsaWJlcmF0ZSBwZW9wbGUgb2YgY29sb3JlZCByYWNlcy4KCiBXaGVuIGV2YWx1YXRpbmcgZW1vdGlvbnMgYW5kIGxlbmd0aCBvZiBQcmVzaWRlbnRzLFByZXNpZGVudCBsaW5jb2xuJ3MgcGFzc2FnZSBhcmUgdmVyeSBjb2xvcmZ1bCBvZiByaHl0aG0gYW5kIGVtb3Rpb25zLCB3ZSBrbm93IGhlIGlzIHZlcnkgZ29vZCBhdCBnaXZpbmcgc3BlZWNoLiBBcyBhIHdob2xlLCBub3J0aGVybiBwcmVzaWRlbnRzIGhhcyBtb3JlIGZlYXIgYW5kIHNhZCBmZWVsaW5ncyB0aGVuIHRoZSBzb3V0aCx3aGlsZSB0aGUgc291dGggYXJlIG1vcmUgam95ZnVsIGFuZCBsaWtlbHkgdG8gc3VycGlzZSwgdGhpcyBtYXkgdG8gZHVlIHRvIGNvbGRuZXNzIG9mIHRoZSBub3J0aCBtYWtpbmcgcGVvcGxlIHNvcnJvdyB3aGlsZSB0aGUgc291dGggaGFzIG1vcmUgc3Vubnkgd2VhdGhlcnMuIHRoZSBjbHVzdGVyIGlzIG5vdCBnb29kIGVub3VnaCB0byBnaXZlIHRoZSBvdmVydmlldyBvZiBhbGwgcHJlc2lkZW50cyBiZWNhdXNlIGVhY2ggcHJlc2lkZW50IGhhcyBoaXMgb3duIHVuaXF1ZSBmZWF0dXJlcwoKIEJ5IHRvcGljIG1vZGVsbGluZyB3ZSBmaW5kIHRoYXQgdGhlIG9sZCB0b3BpYyBhcmUgcXVpdGUgZGlmZmVyZW50IGZyb20gbmV3ZXIgb25lcy5hbmQgdGhlIGhlYXRtYXAgYXJlIG1vcmUgY2xlYXIgdG8gc2hvdyB0aGVyZSBhcmUgc291dGhlcm4gYW5kIG5vcnRoZXJuIHByZXNpZGVudHMgc2VlbSB0byBoYXZlIHNvbWUgaW5uZXIgY29yZXMgLHRoZXkgbWF5IHRoZSBzYW1lIGFuY2llbnQgc3lub255bSBhbmNlc3RyeS4gYW5kIHdlIGFsc28gZmluZCB0aGUgdG9waWNzIHRoZXkgYXJlIHRhbGtpbmcgYWJvdXQgYXJlIHF1aXRlIHRoZSBzYW1lIGJ1dCBub3QgaW4gdGhlIHNhbWUgZm9ybQo=